aboutsummaryrefslogtreecommitdiffstats
path: root/src/java/org/apache
diff options
context:
space:
mode:
Diffstat (limited to 'src/java/org/apache')
-rw-r--r--src/java/org/apache/fop/area/AreaTreeParser.java676
-rw-r--r--src/java/org/apache/fop/area/BeforeFloat.java3
-rw-r--r--src/java/org/apache/fop/area/Block.java12
-rw-r--r--src/java/org/apache/fop/area/BlockParent.java22
-rw-r--r--src/java/org/apache/fop/area/Footnote.java27
-rw-r--r--src/java/org/apache/fop/area/LineArea.java11
-rw-r--r--src/java/org/apache/fop/area/Page.java4
-rw-r--r--src/java/org/apache/fop/area/PageViewport.java18
-rw-r--r--src/java/org/apache/fop/area/RegionReference.java9
-rw-r--r--src/java/org/apache/fop/area/RenderPagesModel.java9
-rw-r--r--src/java/org/apache/fop/area/Trait.java121
-rw-r--r--src/java/org/apache/fop/area/inline/ForeignObject.java20
-rw-r--r--src/java/org/apache/fop/area/inline/InlineArea.java2
-rw-r--r--src/java/org/apache/fop/area/inline/InlineParent.java17
-rw-r--r--src/java/org/apache/fop/area/inline/Leader.java39
-rw-r--r--src/java/org/apache/fop/area/inline/Viewport.java12
-rw-r--r--src/java/org/apache/fop/fo/ElementMapping.java43
-rw-r--r--src/java/org/apache/fop/fo/ElementMappingRegistry.java175
-rw-r--r--src/java/org/apache/fop/fo/FOTreeBuilder.java117
-rw-r--r--src/java/org/apache/fop/fo/extensions/svg/BatikExtensionElementMapping.java15
-rw-r--r--src/java/org/apache/fop/fo/extensions/svg/SVGElementMapping.java24
-rw-r--r--src/java/org/apache/fop/fonts/LazyFont.java1
-rw-r--r--src/java/org/apache/fop/render/XMLHandlerRegistry.java12
-rw-r--r--src/java/org/apache/fop/render/xml/XMLRenderer.java139
-rw-r--r--src/java/org/apache/fop/traits/BorderProps.java93
-rw-r--r--src/java/org/apache/fop/util/DefaultErrorListener.java64
26 files changed, 1433 insertions, 252 deletions
diff --git a/src/java/org/apache/fop/area/AreaTreeParser.java b/src/java/org/apache/fop/area/AreaTreeParser.java
new file mode 100644
index 000000000..32e2bce1e
--- /dev/null
+++ b/src/java/org/apache/fop/area/AreaTreeParser.java
@@ -0,0 +1,676 @@
+/*
+ * Copyright 2006 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$ */
+
+package org.apache.fop.area;
+
+import java.awt.geom.Rectangle2D;
+import java.util.Stack;
+import java.util.StringTokenizer;
+
+import javax.xml.transform.Source;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.dom.DOMResult;
+import javax.xml.transform.sax.SAXResult;
+import javax.xml.transform.sax.SAXTransformerFactory;
+import javax.xml.transform.sax.TransformerHandler;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.apache.fop.apps.FOUserAgent;
+import org.apache.fop.area.Trait.Background;
+import org.apache.fop.area.Trait.Color;
+import org.apache.fop.area.inline.AbstractTextArea;
+import org.apache.fop.area.inline.Character;
+import org.apache.fop.area.inline.ForeignObject;
+import org.apache.fop.area.inline.Image;
+import org.apache.fop.area.inline.InlineBlockParent;
+import org.apache.fop.area.inline.InlineParent;
+import org.apache.fop.area.inline.Leader;
+import org.apache.fop.area.inline.Space;
+import org.apache.fop.area.inline.SpaceArea;
+import org.apache.fop.area.inline.TextArea;
+import org.apache.fop.area.inline.Viewport;
+import org.apache.fop.area.inline.WordArea;
+import org.apache.fop.fo.Constants;
+import org.apache.fop.fo.ElementMappingRegistry;
+import org.apache.fop.fonts.Font;
+import org.apache.fop.fonts.FontTriplet;
+import org.apache.fop.image.FopImage;
+import org.apache.fop.image.ImageFactory;
+import org.apache.fop.traits.BorderProps;
+import org.apache.fop.util.DefaultErrorListener;
+
+import org.w3c.dom.DOMImplementation;
+import org.w3c.dom.Document;
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
+/**
+ * This is a parser for the area tree XML (intermediate format) which is used to reread an area
+ * tree (or part of it) into memory again for rendering to the final output format.
+ */
+public class AreaTreeParser {
+
+ /** Logger instance */
+ protected static Log log = LogFactory.getLog(AreaTreeParser.class);
+
+ private static SAXTransformerFactory tFactory
+ = (SAXTransformerFactory)SAXTransformerFactory.newInstance();
+
+ /**
+ * Parses an intermediate file (area tree XML) into an AreaTreeModel instance by adding
+ * pages to it.
+ * @param src the Source instance pointing to the intermediate file
+ * @param treeModel the AreaTreeModel that the parsed pages are added to
+ * @param userAgent the user agent
+ * @throws TransformerException if an error occurs while parsing the area tree XML
+ */
+ public void parse(Source src, AreaTreeModel treeModel, FOUserAgent userAgent)
+ throws TransformerException {
+ Transformer transformer = tFactory.newTransformer();
+ transformer.setErrorListener(new DefaultErrorListener(log));
+
+ SAXResult res = new SAXResult(getContentHandler(treeModel, userAgent));
+
+ transformer.transform(src, res);
+ }
+
+ /**
+ * Creates a new ContentHandler instance that you can send the area tree XML to. The parsed
+ * pages are added to the AreaTreeModel instance you pass in as a parameter.
+ * @param treeModel the AreaTreeModel that the parsed pages are added to
+ * @param userAgent the user agent
+ * @return the ContentHandler instance to receive the SAX stream from the area tree XML
+ */
+ public ContentHandler getContentHandler(AreaTreeModel treeModel, FOUserAgent userAgent) {
+ //TODO Retrieve this instance from the environment class once it has been created.
+ ElementMappingRegistry elementMappingRegistry = new ElementMappingRegistry(userAgent);
+ return new Handler(treeModel, userAgent, elementMappingRegistry);
+ }
+
+ private static class Handler extends DefaultHandler {
+
+ private AreaTreeModel treeModel;
+ private FOUserAgent userAgent;
+ private ElementMappingRegistry elementMappingRegistry;
+
+ private Attributes lastAttributes;
+ private StringBuffer content = new StringBuffer();
+
+ private PageViewport currentPageViewport;
+ private Stack areaStack = new Stack();
+ private boolean firstFlow;
+
+ private Stack delegateStack = new Stack();
+ private ContentHandler delegate;
+ private DOMImplementation domImplementation;
+
+ public Handler(AreaTreeModel treeModel, FOUserAgent userAgent,
+ ElementMappingRegistry elementMappingRegistry) {
+ this.treeModel = treeModel;
+ this.userAgent = userAgent;
+ this.elementMappingRegistry = elementMappingRegistry;
+ }
+
+ private static Rectangle2D parseRect(String rect) {
+ StringTokenizer tokenizer = new StringTokenizer(rect, " ");
+ return new Rectangle2D.Double(
+ Double.parseDouble(tokenizer.nextToken()),
+ Double.parseDouble(tokenizer.nextToken()),
+ Double.parseDouble(tokenizer.nextToken()),
+ Double.parseDouble(tokenizer.nextToken()));
+ }
+
+ private Area findAreaType(Class clazz) {
+ if (areaStack.size() > 0) {
+ int pos = areaStack.size() - 1;
+ Object obj = null;
+ while (pos >= 0 && !(clazz.isInstance(obj = areaStack.get(pos)))) {
+ pos--;
+ }
+ if (pos >= 0) {
+ return (Area)obj;
+ }
+ }
+ return null;
+ }
+
+ private RegionViewport getCurrentRegionViewport() {
+ return (RegionViewport)findAreaType(RegionViewport.class);
+ }
+
+ private BodyRegion getCurrentBodyRegion() {
+ return (BodyRegion)findAreaType(BodyRegion.class);
+ }
+
+ private BlockParent getCurrentBlockParent() {
+ return (BlockParent)findAreaType(BlockParent.class);
+ }
+
+ private AbstractTextArea getCurrentText() {
+ return (AbstractTextArea)findAreaType(AbstractTextArea.class);
+ }
+
+ private Viewport getCurrentViewport() {
+ return (Viewport)findAreaType(Viewport.class);
+ }
+
+ /** @see org.xml.sax.helpers.DefaultHandler */
+ public void startElement(String uri, String localName, String qName, Attributes attributes)
+ throws SAXException {
+ if (delegate != null) {
+ delegateStack.push(qName);
+ delegate.startElement(uri, localName, qName, attributes);
+ } else if (domImplementation != null) {
+ TransformerHandler handler;
+ try {
+ handler = tFactory.newTransformerHandler();
+ } catch (TransformerConfigurationException e) {
+ throw new SAXException("Error creating a new TransformerHandler", e);
+ }
+ Document doc = domImplementation.createDocument(uri, qName, null);
+ //It's easier to work with an empty document, so remove the root element
+ doc.removeChild(doc.getDocumentElement());
+ handler.setResult(new DOMResult(doc));
+ Area parent = (Area)areaStack.peek();
+ ((ForeignObject)parent).setDocument(doc);
+
+ //activate delegate for nested foreign document
+ this.delegate = handler;
+ delegateStack.push(qName);
+ delegate.startDocument();
+ delegate.startElement(uri, localName, qName, attributes);
+ } else {
+ lastAttributes = attributes;
+ boolean handled = true;
+ if ("".equals(uri)) {
+ if ("areaTree".equals(localName)) {
+ //nop
+ } else if ("pageSequence".equals(localName)) {
+ treeModel.startPageSequence(null);
+ } else if ("pageViewport".equals(localName)) {
+ if (currentPageViewport != null) {
+ throw new IllegalStateException("currentPageViewport must be null");
+ }
+ Rectangle2D viewArea = parseRect(attributes.getValue("bounds"));
+ currentPageViewport = new PageViewport(viewArea, attributes.getValue("nr"));
+ } else if ("page".equals(localName)) {
+ Page p = new Page();
+ currentPageViewport.setPage(p);
+ } else if ("regionViewport".equals(localName)) {
+ RegionViewport rv = getCurrentRegionViewport();
+ if (rv != null) {
+ throw new IllegalStateException("Current RegionViewport must be null");
+ }
+ Rectangle2D viewArea = parseRect(attributes.getValue("rect"));
+ rv = new RegionViewport(viewArea);
+ rv.setClip(getAttributeAsBoolean(attributes, "clipped", false));
+ setAreaAttributes(attributes, rv);
+ setTraits(attributes, rv);
+ areaStack.push(rv);
+ } else if ("regionBefore".equals(localName)) {
+ pushNewRegionReference(attributes, Constants.FO_REGION_BEFORE);
+ } else if ("regionAfter".equals(localName)) {
+ pushNewRegionReference(attributes, Constants.FO_REGION_AFTER);
+ } else if ("regionStart".equals(localName)) {
+ pushNewRegionReference(attributes, Constants.FO_REGION_START);
+ } else if ("regionEnd".equals(localName)) {
+ pushNewRegionReference(attributes, Constants.FO_REGION_END);
+ } else if ("regionBody".equals(localName)) {
+ BodyRegion body = getCurrentBodyRegion();
+ if (body != null) {
+ throw new IllegalStateException("Current BodyRegion must be null");
+ }
+ String regionName = attributes.getValue("name");
+ int columnCount = getAttributeAsInteger(attributes, "columnCount", 1);
+ int columnGap = getAttributeAsInteger(attributes, "columnGap", 0);
+ RegionViewport rv = getCurrentRegionViewport();
+ body = new BodyRegion(Constants.FO_REGION_BODY,
+ regionName, rv, columnCount, columnGap);
+ body.setCTM(getAttributeAsCTM(attributes, "ctm"));
+ setAreaAttributes(attributes, body);
+ rv.setRegionReference(body);
+ currentPageViewport.getPage().setRegionViewport(
+ Constants.FO_REGION_BODY, rv);
+ areaStack.push(body);
+ } else if ("mainReference".equals(localName)) {
+ //mainReference is created by the BodyRegion
+ setAreaAttributes(attributes, getCurrentBodyRegion().getMainReference());
+ } else if ("span".equals(localName)) {
+ int ipd = getAttributeAsInteger(attributes, "ipd", 0);
+ int columnCount = getAttributeAsInteger(attributes, "columnCount", 1);
+ BodyRegion body = getCurrentBodyRegion();
+ Span span = new Span(columnCount,
+ body.getColumnGap(), ipd);
+ setAreaAttributes(attributes, span);
+ body.getMainReference().getSpans().add(span);
+ firstFlow = true;
+ } else if ("flow".equals(localName)) {
+ BodyRegion body = getCurrentBodyRegion();
+ if (!firstFlow) {
+ body.getMainReference().getCurrentSpan().moveToNextFlow();
+ } else {
+ firstFlow = false;
+ }
+ NormalFlow flow = body.getMainReference().getCurrentSpan().getCurrentFlow();
+ setAreaAttributes(attributes, flow);
+ areaStack.push(flow);
+ } else if ("footnote".equals(localName)) {
+ areaStack.push(getCurrentBodyRegion().getFootnote());
+ } else if ("beforeFloat".equals(localName)) {
+ areaStack.push(getCurrentBodyRegion().getBeforeFloat());
+ } else if ("block".equals(localName)) {
+ boolean isViewport = getAttributeAsBoolean(attributes,
+ "is-viewport-area", false);
+ Block block;
+ if (isViewport) {
+ BlockViewport bv = new BlockViewport();
+ bv.setClip(getAttributeAsBoolean(attributes, "clipped", false));
+ bv.setCTM(getAttributeAsCTM(attributes, "ctm"));
+ if (bv.getPositioning() != BlockViewport.RELATIVE) {
+ bv.setXOffset(
+ getAttributeAsInteger(attributes, "left-position", 0));
+ bv.setYOffset(
+ getAttributeAsInteger(attributes, "top-position", 0));
+ }
+ block = bv;
+ } else {
+ block = new Block();
+ }
+ String positioning = attributes.getValue("positioning");
+ if ("absolute".equalsIgnoreCase(positioning)) {
+ block.setPositioning(Block.ABSOLUTE);
+ } else if ("fixed".equalsIgnoreCase(positioning)) {
+ block.setPositioning(Block.FIXED);
+ } else if ("relative".equalsIgnoreCase(positioning)) {
+ block.setPositioning(Block.RELATIVE);
+ } else {
+ block.setPositioning(Block.STACK);
+ }
+ if (attributes.getValue("left-offset") != null) {
+ block.setXOffset(getAttributeAsInteger(attributes, "left-offset", 0));
+ }
+ if (attributes.getValue("top-offset") != null) {
+ block.setYOffset(getAttributeAsInteger(attributes, "top-offset", 0));
+ }
+ setAreaAttributes(attributes, block);
+ setTraits(attributes, block);
+ Area parent = (Area)areaStack.peek();
+ //BlockParent parent = getCurrentBlockParent();
+ parent.addChildArea(block);
+ areaStack.push(block);
+ } else if ("lineArea".equals(localName)) {
+ LineArea line = new LineArea();
+ setAreaAttributes(attributes, line);
+ setTraits(attributes, line);
+ BlockParent parent = getCurrentBlockParent();
+ parent.addChildArea(line);
+ areaStack.push(line);
+ } else if ("inlineparent".equals(localName)) {
+ InlineParent ip = new InlineParent();
+ ip.setOffset(getAttributeAsInteger(attributes, "offset", 0));
+ setAreaAttributes(attributes, ip);
+ setTraits(attributes, ip);
+ Area parent = (Area)areaStack.peek();
+ parent.addChildArea(ip);
+ areaStack.push(ip);
+ } else if ("inlineblockparent".equals(localName)) {
+ InlineBlockParent ibp = new InlineBlockParent();
+ ibp.setOffset(getAttributeAsInteger(attributes, "offset", 0));
+ setAreaAttributes(attributes, ibp);
+ setTraits(attributes, ibp);
+ Area parent = (Area)areaStack.peek();
+ parent.addChildArea(ibp);
+ areaStack.push(ibp);
+ } else if ("text".equals(localName)) {
+ if (getCurrentText() != null) {
+ throw new IllegalStateException("Current Text must be null");
+ }
+ TextArea text = new TextArea();
+ setAreaAttributes(attributes, text);
+ setTraits(attributes, text);
+ text.setBaselineOffset(getAttributeAsInteger(attributes, "baseline", 0));
+ text.setTextLetterSpaceAdjust(getAttributeAsInteger(attributes,
+ "tlsadjust", 0));
+ text.setTextWordSpaceAdjust(getAttributeAsInteger(attributes,
+ "twsadjust", 0));
+ Area parent = (Area)areaStack.peek();
+ parent.addChildArea(text);
+ areaStack.push(text);
+ } else if ("word".equals(localName)) {
+ //handled in endElement
+ } else if ("space".equals(localName)) {
+ //handled in endElement
+ } else if ("char".equals(localName)) {
+ //handled in endElement
+ } else if ("leader".equals(localName)) {
+ Leader leader = new Leader();
+ setAreaAttributes(attributes, leader);
+ setTraits(attributes, leader);
+ leader.setOffset(getAttributeAsInteger(attributes, "offset", 0));
+ String ruleStyle = attributes.getValue("ruleStyle");
+ if (ruleStyle != null) {
+ leader.setRuleStyle(ruleStyle);
+ }
+ leader.setRuleThickness(
+ getAttributeAsInteger(attributes, "ruleThickness", 0));
+ Area parent = (Area)areaStack.peek();
+ parent.addChildArea(leader);
+ } else if ("viewport".equals(localName)) {
+ Viewport viewport = new Viewport(null);
+ setAreaAttributes(attributes, viewport);
+ setTraits(attributes, viewport);
+ viewport.setContentPosition(getAttributeAsRectangle2D(attributes, "pos"));
+ viewport.setClip(getAttributeAsBoolean(attributes, "clip", false));
+ viewport.setOffset(getAttributeAsInteger(attributes, "offset", 0));
+ Area parent = (Area)areaStack.peek();
+ parent.addChildArea(viewport);
+ areaStack.push(viewport);
+ } else if ("image".equals(localName)) {
+ String url = attributes.getValue("url");
+ Image image = new Image(url);
+ setAreaAttributes(attributes, image);
+ setTraits(attributes, image);
+ getCurrentViewport().setContent(image);
+ } else if ("foreignObject".equals(localName)) {
+ String ns = attributes.getValue("ns");
+ this.domImplementation
+ = elementMappingRegistry.getDOMImplementationForNamespace(ns);
+ if (this.domImplementation == null) {
+ throw new SAXException("No DOMImplementation could be"
+ + " identified to handle namespace: " + ns);
+ }
+ ForeignObject foreign = new ForeignObject(ns);
+ setAreaAttributes(attributes, foreign);
+ setTraits(attributes, foreign);
+ getCurrentViewport().setContent(foreign);
+ areaStack.push(foreign);
+ } else {
+ handled = false;
+ }
+ } else {
+ handled = false;
+ }
+ if (!handled) {
+ throw new SAXException("Unhandled element " + localName
+ + " in namespace: " + uri);
+ }
+ }
+ }
+
+ private void pushNewRegionReference(Attributes attributes, int side) {
+ String regionName = attributes.getValue("name");
+ RegionViewport rv = getCurrentRegionViewport();
+ RegionReference reg = new RegionReference(side,
+ regionName, rv);
+ reg.setCTM(getAttributeAsCTM(attributes, "ctm"));
+ setAreaAttributes(attributes, reg);
+ rv.setRegionReference(reg);
+ currentPageViewport.getPage().setRegionViewport(
+ side, rv);
+ areaStack.push(reg);
+ }
+
+ private void assertObjectOfClass(Object obj, Class clazz) {
+ if (!clazz.isInstance(obj)) {
+ throw new IllegalStateException("Object is not an instance of "
+ + clazz.getName() + " but of " + obj.getClass().getName());
+ }
+ }
+
+ /** @see org.xml.sax.helpers.DefaultHandler */
+ public void endElement(String uri, String localName, String qName) throws SAXException {
+ if (delegate != null) {
+ delegate.endElement(uri, localName, qName);
+ delegateStack.pop();
+ if (delegateStack.size() == 0) {
+ delegate.endDocument();
+ delegate = null;
+ domImplementation = null;
+ }
+ } else {
+ if ("".equals(uri)) {
+ if ("pageSequence".equals(localName)) {
+ //end page-sequence
+ } else if ("page".equals(localName)) {
+ treeModel.addPage(currentPageViewport);
+ currentPageViewport = null;
+ } else if ("pageViewport".equals(localName)) {
+ //nop
+ } else if ("regionViewport".equals(localName)) {
+ assertObjectOfClass(areaStack.pop(), RegionViewport.class);
+ } else if ("regionBefore".equals(localName)) {
+ assertObjectOfClass(areaStack.pop(), RegionReference.class);
+ } else if ("regionAfter".equals(localName)) {
+ assertObjectOfClass(areaStack.pop(), RegionReference.class);
+ } else if ("regionStart".equals(localName)) {
+ assertObjectOfClass(areaStack.pop(), RegionReference.class);
+ } else if ("regionEnd".equals(localName)) {
+ assertObjectOfClass(areaStack.pop(), RegionReference.class);
+ } else if ("regionBody".equals(localName)) {
+ assertObjectOfClass(areaStack.pop(), BodyRegion.class);
+ } else if ("flow".equals(localName)) {
+ assertObjectOfClass(areaStack.pop(), NormalFlow.class);
+ } else if ("footnote".equals(localName)) {
+ assertObjectOfClass(areaStack.pop(), Footnote.class);
+ } else if ("beforeFloat".equals(localName)) {
+ assertObjectOfClass(areaStack.pop(), BeforeFloat.class);
+ } else if ("block".equals(localName)) {
+ assertObjectOfClass(areaStack.pop(), Block.class);
+ } else if ("lineArea".equals(localName)) {
+ assertObjectOfClass(areaStack.pop(), LineArea.class);
+ } else if ("inlineparent".equals(localName)) {
+ assertObjectOfClass(areaStack.pop(), InlineParent.class);
+ } else if ("inlineblockparent".equals(localName)) {
+ assertObjectOfClass(areaStack.pop(), InlineBlockParent.class);
+ } else if ("text".equals(localName)) {
+ assertObjectOfClass(areaStack.pop(), TextArea.class);
+ } else if ("word".equals(localName)) {
+ int offset = getAttributeAsInteger(lastAttributes, "offset", 0);
+ String txt = content.toString();
+ WordArea word = new WordArea(txt, offset);
+ AbstractTextArea text = getCurrentText();
+ word.setParentArea(text);
+ text.addChildArea(word);
+ } else if ("space".equals(localName)) {
+ int offset = getAttributeAsInteger(lastAttributes, "offset", 0);
+ String txt = content.toString();
+ //TODO the isAdjustable parameter is currently not used/implemented
+ if (txt.length() > 0) {
+ SpaceArea space = new SpaceArea(txt.charAt(0), offset, false);
+ AbstractTextArea text = getCurrentText();
+ space.setParentArea(text);
+ text.addChildArea(space);
+ } else {
+ Space space = new Space();
+ setAreaAttributes(lastAttributes, space);
+ setTraits(lastAttributes, space);
+ space.setOffset(getAttributeAsInteger(lastAttributes, "offset", 0));
+ Area parent = (Area)areaStack.peek();
+ parent.addChildArea(space);
+ }
+ } else if ("char".equals(localName)) {
+ String txt = content.toString();
+ Character ch = new Character(txt.charAt(0));
+ setAreaAttributes(lastAttributes, ch);
+ setTraits(lastAttributes, ch);
+ ch.setOffset(getAttributeAsInteger(lastAttributes, "offset", 0));
+ ch.setBaselineOffset(getAttributeAsInteger(lastAttributes, "baseline", 0));
+ Area parent = (Area)areaStack.peek();
+ parent.addChildArea(ch);
+ } else if ("viewport".equals(localName)) {
+ assertObjectOfClass(areaStack.pop(), Viewport.class);
+ } else if ("foreignObject".equals(localName)) {
+ assertObjectOfClass(areaStack.pop(), ForeignObject.class);
+ }
+ } else {
+ //log.debug("Ignoring " + localName + " in namespace: " + uri);
+ }
+ content.setLength(0); //Reset text buffer (see characters())
+ }
+ }
+
+ private void setAreaAttributes(Attributes attributes, Area area) {
+ area.setIPD(Integer.parseInt(attributes.getValue("ipd")));
+ area.setBPD(Integer.parseInt(attributes.getValue("bpd")));
+ }
+
+ private void setTraits(Attributes attributes, Area area) {
+ for (int i = 0, c = Trait.TRAIT_LIST.length; i < c; i++) {
+ Object trait = Trait.TRAIT_LIST[i];
+ Class cl = Trait.getTraitClass(trait);
+ if (cl == Boolean.class) {
+ String value = attributes.getValue(Trait.getTraitName(trait));
+ if (value != null) {
+ area.addTrait(trait, Boolean.valueOf(value));
+ }
+ } else if (cl == Integer.class) {
+ String value = attributes.getValue(Trait.getTraitName(trait));
+ if (value != null) {
+ area.addTrait(trait, new Integer(value));
+ }
+ } else if (cl == String.class) {
+ String value = attributes.getValue(Trait.getTraitName(trait));
+ if (value != null) {
+ area.addTrait(trait, value);
+ }
+ } else if (cl == FontTriplet.class) {
+ String fontName = attributes.getValue("font-name");
+ if (fontName != null) {
+ String fontStyle = attributes.getValue("font-style");
+ int fontWeight = getAttributeAsInteger(
+ attributes, "font-weight", Font.NORMAL);
+ area.addTrait(trait,
+ new FontTriplet(fontName, fontStyle, fontWeight));
+ }
+ } else if (cl == Color.class) {
+ String value = attributes.getValue(Trait.getTraitName(trait));
+ if (value != null) {
+ area.addTrait(trait, Color.valueOf(value));
+ }
+ } else if (cl == Background.class) {
+ String value = attributes.getValue(Trait.getTraitName(trait));
+ if (value != null) {
+ Background bkg = new Background();
+ Color col = Color.valueOf(attributes.getValue("bkg-color"));
+ if (col != null) {
+ bkg.setColor(col);
+ }
+ String url = attributes.getValue("bkg-img");
+ if (url != null) {
+ bkg.setURL(url);
+
+ ImageFactory fact = ImageFactory.getInstance();
+ FopImage img = fact.getImage(url, userAgent);
+ if (img == null) {
+ log.error("Background image not available: " + url);
+ } else {
+ // load dimensions
+ if (!img.load(FopImage.DIMENSIONS)) {
+ log.error("Cannot read background image dimensions: "
+ + url);
+ }
+ }
+ bkg.setFopImage(img);
+
+ String repeat = attributes.getValue("bkg-repeat");
+ if (repeat != null) {
+ bkg.setRepeat(repeat);
+ }
+ bkg.setHoriz(getAttributeAsInteger(attributes,
+ "bkg-horz-offset", 0));
+ bkg.setVertical(getAttributeAsInteger(attributes,
+ "bkg-vert-offset", 0));
+ }
+ area.addTrait(trait, bkg);
+ }
+ } else if (cl == BorderProps.class) {
+ String value = attributes.getValue(Trait.getTraitName(trait));
+ if (value != null) {
+ area.addTrait(trait, BorderProps.valueOf(value));
+ }
+ }
+ }
+ }
+
+ private boolean getAttributeAsBoolean(Attributes attributes, String name,
+ boolean defaultValue) {
+ String s = attributes.getValue(name);
+ if (s == null) {
+ return defaultValue;
+ } else {
+ return Boolean.valueOf(s).booleanValue();
+ }
+ }
+
+ private int getAttributeAsInteger(Attributes attributes, String name,
+ int defaultValue) {
+ String s = attributes.getValue(name);
+ if (s == null) {
+ return defaultValue;
+ } else {
+ return Integer.parseInt(s);
+ }
+ }
+
+ private CTM getAttributeAsCTM(Attributes attributes, String name) {
+ String s = attributes.getValue(name).trim();
+ if (s.startsWith("[") && s.endsWith("]")) {
+ s = s.substring(1, s.length() - 1);
+ StringTokenizer tokenizer = new StringTokenizer(s, " ");
+ double[] values = new double[] {
+ Double.parseDouble(tokenizer.nextToken()),
+ Double.parseDouble(tokenizer.nextToken()),
+ Double.parseDouble(tokenizer.nextToken()),
+ Double.parseDouble(tokenizer.nextToken()),
+ Double.parseDouble(tokenizer.nextToken()),
+ Double.parseDouble(tokenizer.nextToken())};
+ return new CTM(values[0], values[1], values[2], values[3], values[4], values[5]);
+ } else {
+ throw new IllegalArgumentException("CTM must be surrounded by square brackets");
+ }
+ }
+
+ private Rectangle2D getAttributeAsRectangle2D(Attributes attributes, String name) {
+ String s = attributes.getValue(name).trim();
+ StringTokenizer tokenizer = new StringTokenizer(s, " ");
+ double[] values = new double[] {
+ Double.parseDouble(tokenizer.nextToken()),
+ Double.parseDouble(tokenizer.nextToken()),
+ Double.parseDouble(tokenizer.nextToken()),
+ Double.parseDouble(tokenizer.nextToken())};
+ return new Rectangle2D.Double(values[0], values[1], values[2], values[3]);
+ }
+
+ /** @see org.xml.sax.ContentHandler#characters(char[], int, int) */
+ public void characters(char[] ch, int start, int length) throws SAXException {
+ if (delegate != null) {
+ delegate.characters(ch, start, length);
+ } else {
+ content.append(ch, start, length);
+ }
+ }
+
+ }
+
+}
diff --git a/src/java/org/apache/fop/area/BeforeFloat.java b/src/java/org/apache/fop/area/BeforeFloat.java
index 2db35a635..4ebbaf296 100644
--- a/src/java/org/apache/fop/area/BeforeFloat.java
+++ b/src/java/org/apache/fop/area/BeforeFloat.java
@@ -1,5 +1,5 @@
/*
- * Copyright 1999-2005 The Apache Software Foundation.
+ * Copyright 1999-2006 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.
@@ -61,6 +61,7 @@ public class BeforeFloat extends BlockParent {
return h;
}
+ /** @see org.apache.fop.area.BlockParent#isEmpty() */
public boolean isEmpty() {
return true; // before floats are not yet implemented
}
diff --git a/src/java/org/apache/fop/area/Block.java b/src/java/org/apache/fop/area/Block.java
index 700334e77..f51bb7efc 100644
--- a/src/java/org/apache/fop/area/Block.java
+++ b/src/java/org/apache/fop/area/Block.java
@@ -1,5 +1,5 @@
/*
- * Copyright 1999-2005 The Apache Software Foundation.
+ * Copyright 1999-2006 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.
@@ -77,13 +77,10 @@ public class Block extends BlockParent {
* @param autoHeight increase the height of the block.
*/
public void addBlock(Block block, boolean autoHeight) {
- if (children == null) {
- children = new ArrayList();
- }
if (autoHeight) {
bpd += block.getAllocBPD();
}
- children.add(block);
+ addChildArea(block);
}
/**
@@ -92,11 +89,8 @@ public class Block extends BlockParent {
* @param line the line area to add
*/
public void addLineArea(LineArea line) {
- if (children == null) {
- children = new ArrayList();
- }
bpd += line.getAllocBPD();
- children.add(line);
+ addChildArea(line);
}
/**
diff --git a/src/java/org/apache/fop/area/BlockParent.java b/src/java/org/apache/fop/area/BlockParent.java
index 63b35ca24..fe6650dbc 100644
--- a/src/java/org/apache/fop/area/BlockParent.java
+++ b/src/java/org/apache/fop/area/BlockParent.java
@@ -52,16 +52,21 @@ public class BlockParent extends Area {
// orientation if reference area
private int orientation = ORIENT_0;
+ /** @see org.apache.fop.area.Area#addChildArea(org.apache.fop.area.Area) */
+ public void addChildArea(Area childArea) {
+ if (children == null) {
+ children = new ArrayList();
+ }
+ children.add(childArea);
+ }
+
/**
* Add the block area to this block parent.
*
* @param block the child block area to add
*/
public void addBlock(Block block) {
- if (children == null) {
- children = new ArrayList();
- }
- children.add(block);
+ addChildArea(block);
}
/**
@@ -74,6 +79,15 @@ public class BlockParent extends Area {
}
/**
+ * Check whether there are child areas.
+ *
+ * @return the result.
+ */
+ public boolean isEmpty() {
+ return children == null || children.size() == 0;
+ }
+
+ /**
* Set the X offset of this block parent area.
*
* @param off the x offset of the block parent area
diff --git a/src/java/org/apache/fop/area/Footnote.java b/src/java/org/apache/fop/area/Footnote.java
index 735dfaf25..afa12afaf 100644
--- a/src/java/org/apache/fop/area/Footnote.java
+++ b/src/java/org/apache/fop/area/Footnote.java
@@ -1,5 +1,5 @@
/*
- * Copyright 1999-2005 The Apache Software Foundation.
+ * Copyright 1999-2006 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.
@@ -18,9 +18,6 @@
package org.apache.fop.area;
-import java.util.ArrayList;
-import java.util.List;
-
// may combine with before float into a conditional area
/**
@@ -80,29 +77,9 @@ public class Footnote extends BlockParent {
* @param child the block area.
*/
public void addBlock(Block child) {
- if (children == null) {
- children = new ArrayList();
- }
+ addChildArea(child);
this.setBPD(this.getBPD() + child.getBPD());
- children.add(child);
- }
-
- /**
- * Get all child areas.
- *
- * @return the list of child areas. Maybe null.
- */
- public List getChildAreas() {
- return children;
}
- /**
- * Check whether there are child areas.
- *
- * @return the result.
- */
- public boolean isEmpty() {
- return children == null || children.size() == 0;
- }
}
diff --git a/src/java/org/apache/fop/area/LineArea.java b/src/java/org/apache/fop/area/LineArea.java
index 15d22548f..e19e71374 100644
--- a/src/java/org/apache/fop/area/LineArea.java
+++ b/src/java/org/apache/fop/area/LineArea.java
@@ -1,5 +1,5 @@
/*
- * Copyright 1999-2005 The Apache Software Foundation.
+ * Copyright 1999-2006 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.
@@ -57,13 +57,13 @@ public class LineArea extends Area {
private LineAdjustingInfo adjustingInfo = null;
- private int stacking = LR;
+ //private int stacking = LR;
// contains inline areas
// has start indent and length, dominant baseline, height
private int startIndent;
// this is the offset for the dominant baseline
- private int baseLine;
+ //private int baseLine;
// this class can contain the dominant char styling info
// this means that many renderers can optimise a bit
@@ -82,6 +82,8 @@ public class LineArea extends Area {
* a new LineAdjustingInfo object is created
* @param alignment alignment of this line
* @param diff difference between content width and line width
+ * @param stretch the available stretch for any adjustments
+ * @param shrink the available shrink for any adjustments
*/
public LineArea(int alignment, int diff,
int stretch, int shrink) {
@@ -185,7 +187,8 @@ public class LineArea extends Area {
break;
case Constants.EN_JUSTIFY:
// compute variation factor
- adjustingInfo.variationFactor *= (float) (adjustingInfo.difference - ipdVariation) / adjustingInfo.difference;
+ adjustingInfo.variationFactor *= (float) (adjustingInfo.difference - ipdVariation)
+ / adjustingInfo.difference;
adjustingInfo.difference -= ipdVariation;
// if the LineArea has already been added to the area tree,
// call finalize(); otherwise, wait for the LineLM to call it
diff --git a/src/java/org/apache/fop/area/Page.java b/src/java/org/apache/fop/area/Page.java
index cc920b993..a0ad2e877 100644
--- a/src/java/org/apache/fop/area/Page.java
+++ b/src/java/org/apache/fop/area/Page.java
@@ -1,5 +1,5 @@
/*
- * Copyright 1999-2005 The Apache Software Foundation.
+ * Copyright 1999-2006 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.
@@ -187,7 +187,7 @@ public class Page implements Serializable, Cloneable {
* @param areaclass the area class of the region to set
* @param port the region viewport to set
*/
- private void setRegionViewport(int areaclass, RegionViewport port) {
+ public void setRegionViewport(int areaclass, RegionViewport port) {
if (areaclass == Constants.FO_REGION_BEFORE) {
regionBefore = port;
} else if (areaclass == Constants.FO_REGION_START) {
diff --git a/src/java/org/apache/fop/area/PageViewport.java b/src/java/org/apache/fop/area/PageViewport.java
index f1daaa2f1..b516b3446 100644
--- a/src/java/org/apache/fop/area/PageViewport.java
+++ b/src/java/org/apache/fop/area/PageViewport.java
@@ -108,6 +108,16 @@ public class PageViewport implements Resolvable, Cloneable {
}
/**
+ * Constructor used by the area tree parser.
+ * @param viewArea the view area
+ * @param pageStr String representation of the page number
+ */
+ public PageViewport(Rectangle2D viewArea, String pageStr) {
+ this.viewArea = viewArea;
+ this.pageNumberString = pageStr;
+ }
+
+ /**
* Get the view area rectangle of this viewport.
* @return the rectangle for this viewport
*/
@@ -122,6 +132,14 @@ public class PageViewport implements Resolvable, Cloneable {
public Page getPage() {
return page;
}
+
+ /**
+ * Sets the page object for this PageViewport.
+ * @param page the page
+ */
+ public void setPage(Page page) {
+ this.page = page;
+ }
/**
* Get the page number of this page.
diff --git a/src/java/org/apache/fop/area/RegionReference.java b/src/java/org/apache/fop/area/RegionReference.java
index b643db4dc..eb85fc4b8 100644
--- a/src/java/org/apache/fop/area/RegionReference.java
+++ b/src/java/org/apache/fop/area/RegionReference.java
@@ -1,5 +1,5 @@
/*
- * Copyright 1999-2005 The Apache Software Foundation.
+ * Copyright 1999-2006 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.
@@ -67,6 +67,11 @@ public class RegionReference extends Area implements Cloneable {
regionViewport = parent;
}
+ /** @see org.apache.fop.area.Area#addChildArea(org.apache.fop.area.Area) */
+ public void addChildArea(Area child) {
+ blocks.add(child);
+ }
+
/**
* Set the Coordinate Transformation Matrix which transforms content
* coordinates in this region reference area which are specified in
@@ -125,7 +130,7 @@ public class RegionReference extends Area implements Cloneable {
* @param block the block area to add
*/
public void addBlock(Block block) {
- blocks.add(block);
+ addChildArea(block);
}
/**
diff --git a/src/java/org/apache/fop/area/RenderPagesModel.java b/src/java/org/apache/fop/area/RenderPagesModel.java
index 3f44ee736..f4ae85fe7 100644
--- a/src/java/org/apache/fop/area/RenderPagesModel.java
+++ b/src/java/org/apache/fop/area/RenderPagesModel.java
@@ -1,5 +1,5 @@
/*
- * Copyright 1999-2005 The Apache Software Foundation.
+ * Copyright 1999-2006 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.
@@ -113,8 +113,11 @@ public class RenderPagesModel extends AreaTreeModel {
try {
renderer.renderPage(page);
} catch (Exception e) {
- // use error handler to handle this FOP or IO Exception
- log.error(e);
+ //TODO use error handler to handle this FOP or IO Exception or propagate exception
+ String err = "Error while rendering page " + page.getPageNumberString();
+ log.error(err, e);
+ throw new IllegalStateException("Fatal error occurred. Cannot continue. "
+ + e.getClass().getName() + ": " + err);
}
page.clear();
} else {
diff --git a/src/java/org/apache/fop/area/Trait.java b/src/java/org/apache/fop/area/Trait.java
index 0dd1c5681..a58d527a9 100644
--- a/src/java/org/apache/fop/area/Trait.java
+++ b/src/java/org/apache/fop/area/Trait.java
@@ -1,5 +1,5 @@
/*
- * Copyright 1999-2005 The Apache Software Foundation.
+ * Copyright 1999-2006 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.
@@ -202,6 +202,9 @@ public class Trait implements Serializable {
public static final Integer LINETHROUGH_COLOR = new Integer(36);
private static final Map TRAIT_INFO = new HashMap();
+
+ /** The list of simple traits in order to avoid iterators */
+ public static final Object[] TRAIT_LIST;
private static class TraitInfo {
private String name;
@@ -232,19 +235,19 @@ public class Trait implements Serializable {
new TraitInfo("font", FontTriplet.class));
TRAIT_INFO.put(FONT_SIZE,
new TraitInfo("font-size", Integer.class));
- TRAIT_INFO.put(COLOR, new TraitInfo("color", String.class));
+ TRAIT_INFO.put(COLOR, new TraitInfo("color", Color.class));
TRAIT_INFO.put(PROD_ID, new TraitInfo("prod-id", String.class));
TRAIT_INFO.put(BACKGROUND,
new TraitInfo("background", Background.class));
TRAIT_INFO.put(UNDERLINE,
new TraitInfo("underline-score", Boolean.class));
- TRAIT_INFO.put(UNDERLINE_COLOR, new TraitInfo("underline-score-color", String.class));
+ TRAIT_INFO.put(UNDERLINE_COLOR, new TraitInfo("underline-score-color", Color.class));
TRAIT_INFO.put(OVERLINE,
new TraitInfo("overline-score", Boolean.class));
- TRAIT_INFO.put(OVERLINE_COLOR, new TraitInfo("overline-score-color", String.class));
+ TRAIT_INFO.put(OVERLINE_COLOR, new TraitInfo("overline-score-color", Color.class));
TRAIT_INFO.put(LINETHROUGH,
new TraitInfo("through-score", Boolean.class));
- TRAIT_INFO.put(LINETHROUGH_COLOR, new TraitInfo("through-score-color", String.class));
+ TRAIT_INFO.put(LINETHROUGH_COLOR, new TraitInfo("through-score-color", Color.class));
TRAIT_INFO.put(BLINK,
new TraitInfo("blink", Boolean.class));
TRAIT_INFO.put(OFFSET, new TraitInfo("offset", Integer.class));
@@ -285,6 +288,8 @@ public class Trait implements Serializable {
new TraitInfo("is-reference-area", Boolean.class));
TRAIT_INFO.put(IS_VIEWPORT_AREA,
new TraitInfo("is-viewport-area", Boolean.class));
+
+ TRAIT_LIST = TRAIT_INFO.keySet().toArray();
}
/**
@@ -326,7 +331,7 @@ public class Trait implements Serializable {
* @param oTraitCode the trait code to lookup
* @return the class type for the trait
*/
- private static Class getTraitClass(Object oTraitCode) {
+ public static Class getTraitClass(Object oTraitCode) {
TraitInfo ti = (TraitInfo) TRAIT_INFO.get(oTraitCode);
return (ti != null ? ti.getClazz() : null);
}
@@ -496,6 +501,51 @@ public class Trait implements Serializable {
}
}
+ /** @see java.lang.Object#hashCode() */
+ public int hashCode() {
+ return toString().hashCode();
+ }
+
+ /** @see java.lang.Object#equals(java.lang.Object) */
+ public boolean equals(Object obj) {
+ if (obj == null) {
+ return false;
+ } else if (obj == this) {
+ return true;
+ } else {
+ if (obj instanceof ColorType) {
+ ColorType other = (ColorType)obj;
+ return getRed() == other.getRed()
+ && getGreen() == other.getGreen()
+ && getBlue() == other.getBlue()
+ && getAlpha() == other.getAlpha();
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Returns a Color represtation of a string of the format "#RRGGBB".
+ * @param s the string
+ * @return the Color value
+ */
+ public static Color valueOf(String s) {
+ if (s == null) {
+ return null;
+ }
+ if (!s.startsWith("#")) {
+ throw new IllegalArgumentException("Color must start with '#'");
+ }
+ int r = Integer.parseInt(s.substring(1, 3), 16);
+ int g = Integer.parseInt(s.substring(3, 5), 16);
+ int b = Integer.parseInt(s.substring(5, 7), 16);
+ int a = 255;
+ if (s.length() > 7) {
+ a = Integer.parseInt(s.substring(7, 9), 16);
+ }
+ return new Color(r / 255.0f, g / 255.0f, b / 255.0f, a / 255.0f);
+ }
+
/** @see java.lang.Object#toString() */
public String toString() {
StringBuffer sbuf = new StringBuffer(8);
@@ -515,6 +565,13 @@ public class Trait implements Serializable {
sbuf.append('0');
}
sbuf.append(s);
+ if (alpha != 1) {
+ s = Integer.toHexString((int)(alpha * 255.0));
+ if (s.length() == 1) {
+ sbuf.append('0');
+ }
+ sbuf.append(s);
+ }
return sbuf.toString();
}
@@ -617,6 +674,14 @@ public class Trait implements Serializable {
}
/**
+ * Sets the image repetition behaviour for images.
+ * @param repeat The image repetition behaviour to set
+ */
+ public void setRepeat(String repeat) {
+ setRepeat(getConstantForRepeat(repeat));
+ }
+
+ /**
* Sets the URL to the background image.
* @param url The URL to set
*/
@@ -640,7 +705,31 @@ public class Trait implements Serializable {
this.vertical = vertical;
}
- /**
+ private String getRepeatString() {
+ switch (getRepeat()) {
+ case Constants.EN_REPEAT: return "repeat";
+ case Constants.EN_REPEATX: return "repeat-x";
+ case Constants.EN_REPEATY: return "repeat-y";
+ case Constants.EN_NOREPEAT: return "no-repeat";
+ default: throw new IllegalStateException("Illegal repeat style: " + getRepeat());
+ }
+ }
+
+ private static int getConstantForRepeat(String repeat) {
+ if ("repeat".equalsIgnoreCase(repeat)) {
+ return Constants.EN_REPEAT;
+ } else if ("repeat-x".equalsIgnoreCase(repeat)) {
+ return Constants.EN_REPEATX;
+ } else if ("repeat-y".equalsIgnoreCase(repeat)) {
+ return Constants.EN_REPEATY;
+ } else if ("no-repeat".equalsIgnoreCase(repeat)) {
+ return Constants.EN_NOREPEAT;
+ } else {
+ throw new IllegalStateException("Illegal repeat style: " + repeat);
+ }
+ }
+
+ /**
* Return the string for debugging.
* @see java.lang.Object#toString()
*/
@@ -649,23 +738,7 @@ public class Trait implements Serializable {
sb.append("color=").append(color);
if (url != null) {
sb.append(",url=").append(url);
- sb.append(",repeat=");
- switch (repeat) {
- case Constants.EN_REPEAT:
- sb.append("repeat");
- break;
- case Constants.EN_REPEATX:
- sb.append("repeat-x");
- break;
- case Constants.EN_REPEATY:
- sb.append("repeat-y");
- break;
- case Constants.EN_NOREPEAT:
- sb.append("no-repeat");
- break;
- default:
- sb.append("ILLEGAL!");
- }
+ sb.append(",repeat=").append(getRepeatString());
sb.append(",horiz=").append(horiz);
sb.append(",vertical=").append(vertical);
}
diff --git a/src/java/org/apache/fop/area/inline/ForeignObject.java b/src/java/org/apache/fop/area/inline/ForeignObject.java
index 7bf24963d..8a47be6e1 100644
--- a/src/java/org/apache/fop/area/inline/ForeignObject.java
+++ b/src/java/org/apache/fop/area/inline/ForeignObject.java
@@ -1,5 +1,5 @@
/*
- * Copyright 1999-2004 The Apache Software Foundation.
+ * Copyright 1999-2004,2006 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.
@@ -29,6 +29,7 @@ import org.w3c.dom.Document;
* This holds an xml document and the associated namespace.
*/
public class ForeignObject extends Area {
+
private Document doc;
private String namespace;
@@ -44,6 +45,23 @@ public class ForeignObject extends Area {
}
/**
+ * Create a new empty foreign object for which the DOM Document will be set later.
+ *
+ * @param ns the namespace of the document
+ */
+ public ForeignObject(String ns) {
+ namespace = ns;
+ }
+
+ /**
+ * Sets the DOM document for this foreign object.
+ * @param document the DOM document
+ */
+ public void setDocument(Document document) {
+ this.doc = document;
+ }
+
+ /**
* Get the document for this foreign object.
*
* @return the xml document
diff --git a/src/java/org/apache/fop/area/inline/InlineArea.java b/src/java/org/apache/fop/area/inline/InlineArea.java
index 2f326823b..d4e0f47cf 100644
--- a/src/java/org/apache/fop/area/inline/InlineArea.java
+++ b/src/java/org/apache/fop/area/inline/InlineArea.java
@@ -1,5 +1,5 @@
/*
- * Copyright 1999-2005 The Apache Software Foundation.
+ * Copyright 1999-2006 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.
diff --git a/src/java/org/apache/fop/area/inline/InlineParent.java b/src/java/org/apache/fop/area/inline/InlineParent.java
index 6444da8c4..122c8b2c9 100644
--- a/src/java/org/apache/fop/area/inline/InlineParent.java
+++ b/src/java/org/apache/fop/area/inline/InlineParent.java
@@ -1,5 +1,5 @@
/*
- * Copyright 1999-2005 The Apache Software Foundation.
+ * Copyright 1999-2006 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.
@@ -33,11 +33,9 @@ public class InlineParent extends InlineArea {
*/
protected List inlines = new ArrayList();
- /**
- * An inline parent is a reference area somay have clipping
- */
- protected boolean clip = false;
-
+ /** Controls whether the IPD is automatically adjusted based on the area's children. */
+ protected transient boolean autoSize;
+
/**
* Create a new inline parent to add areas to.
*/
@@ -50,9 +48,14 @@ public class InlineParent extends InlineArea {
* @param childArea the child area to add
*/
public void addChildArea(Area childArea) {
+ if (inlines.size() == 0) {
+ autoSize = (getIPD() == 0);
+ }
if (childArea instanceof InlineArea) {
inlines.add(childArea);
- increaseIPD(((InlineArea) childArea).getAllocIPD());
+ if (autoSize) {
+ increaseIPD(((InlineArea) childArea).getAllocIPD());
+ }
}
}
diff --git a/src/java/org/apache/fop/area/inline/Leader.java b/src/java/org/apache/fop/area/inline/Leader.java
index f683b5af0..e68469b01 100644
--- a/src/java/org/apache/fop/area/inline/Leader.java
+++ b/src/java/org/apache/fop/area/inline/Leader.java
@@ -1,5 +1,5 @@
/*
- * Copyright 1999-2004 The Apache Software Foundation.
+ * Copyright 1999-2004,2006 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.
@@ -50,6 +50,28 @@ public class Leader extends InlineArea {
}
/**
+ * Set the rule style of this leader area.
+ * @param style the rule style for the leader area (XSL enum values)
+ */
+ public void setRuleStyle(String style) {
+ if ("dotted".equalsIgnoreCase(style)) {
+ setRuleStyle(Constants.EN_DOTTED);
+ } else if ("dashed".equalsIgnoreCase(style)) {
+ setRuleStyle(Constants.EN_DASHED);
+ } else if ("solid".equalsIgnoreCase(style)) {
+ setRuleStyle(Constants.EN_SOLID);
+ } else if ("double".equalsIgnoreCase(style)) {
+ setRuleStyle(Constants.EN_DOUBLE);
+ } else if ("groove".equalsIgnoreCase(style)) {
+ setRuleStyle(Constants.EN_GROOVE);
+ } else if ("ridge".equalsIgnoreCase(style)) {
+ setRuleStyle(Constants.EN_RIDGE);
+ } else if ("none".equalsIgnoreCase(style)) {
+ setRuleStyle(Constants.EN_NONE);
+ }
+ }
+
+ /**
* Set the rule thickness of the rule in miilipoints.
*
* @param rt the rule thickness in millipoints
@@ -67,6 +89,21 @@ public class Leader extends InlineArea {
return ruleStyle;
}
+ /** @return the rule style as string */
+ public String getRuleStyleAsString() {
+ switch (getRuleStyle()) {
+ case Constants.EN_DOTTED: return "dotted";
+ case Constants.EN_DASHED: return "dashed";
+ case Constants.EN_SOLID: return "solid";
+ case Constants.EN_DOUBLE: return "double";
+ case Constants.EN_GROOVE: return "groove";
+ case Constants.EN_RIDGE: return "ridge";
+ case Constants.EN_NONE: return "none";
+ default:
+ throw new IllegalStateException("Unsupported rule style: " + getRuleStyle());
+ }
+ }
+
/**
* Get the rule thickness of the rule in miilipoints.
*
diff --git a/src/java/org/apache/fop/area/inline/Viewport.java b/src/java/org/apache/fop/area/inline/Viewport.java
index c9c0b5b10..e8035a904 100644
--- a/src/java/org/apache/fop/area/inline/Viewport.java
+++ b/src/java/org/apache/fop/area/inline/Viewport.java
@@ -1,5 +1,5 @@
/*
- * Copyright 1999-2004 The Apache Software Foundation.
+ * Copyright 1999-2004,2006 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.
@@ -35,7 +35,7 @@ public class Viewport extends InlineArea {
private Area content;
// clipping for the viewport
private boolean clip = false;
- // position of the cild area relative to this area
+ // position of the child area relative to this area
private Rectangle2D contentPosition;
/**
@@ -84,6 +84,14 @@ public class Viewport extends InlineArea {
}
/**
+ * Sets the content area.
+ * @param content the content area
+ */
+ public void setContent(Area content) {
+ this.content = content;
+ }
+
+ /**
* Get the content area for this viewport.
*
* @return the content area
diff --git a/src/java/org/apache/fop/fo/ElementMapping.java b/src/java/org/apache/fop/fo/ElementMapping.java
index 3501194ab..092a411f0 100644
--- a/src/java/org/apache/fop/fo/ElementMapping.java
+++ b/src/java/org/apache/fop/fo/ElementMapping.java
@@ -1,5 +1,5 @@
/*
- * Copyright 1999-2004 The Apache Software Foundation.
+ * Copyright 1999-2004,2006 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.
@@ -20,6 +20,11 @@ package org.apache.fop.fo;
import java.util.HashMap;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.w3c.dom.DOMImplementation;
+
/**
* Abstract base class for Element Mappings (including FO Element Mappings)
* which provide the framework of valid elements and attibutes for a given
@@ -55,14 +60,50 @@ public abstract class ElementMapping {
public String getNamespaceURI() {
return namespaceURI;
}
+
+ /**
+ * Returns the DOMImplementation used by this ElementMapping. The value returned may be null
+ * for cases where no DOM is used to represent the element tree (XSL-FO, for example). This
+ * method is used by the intermediate format to instantiate the right kind of DOM document
+ * for foreign objects. For example, SVG handled through Apache Batik has to use a special
+ * DOMImplementation.
+ * @return the DOMImplementation used by this ElementMapping, may be null
+ */
+ public DOMImplementation getDOMImplementation() {
+ return null; //For namespaces not used in foreign objects
+ }
/**
+ * @return the default DOMImplementation when no specialized DOM is necessary.
+ */
+ protected DOMImplementation getDefaultDOMImplementation() {
+ DocumentBuilderFactory fact = DocumentBuilderFactory.newInstance();
+ fact.setNamespaceAware(true);
+ fact.setValidating(false);
+ try {
+ return fact.newDocumentBuilder().getDOMImplementation();
+ } catch (ParserConfigurationException e) {
+ throw new RuntimeException(
+ "Cannot return default DOM implementation: " + e.getMessage());
+ }
+ }
+
+ /**
* Initializes the set of maker objects associated with this ElementMapping
*/
protected abstract void initialize();
+ /**
+ * Base class for all Makers. It is responsible to return the right kind of FONode for a
+ * particular element.
+ */
public static class Maker {
+ /**
+ * Creates a new FONode (or rather a specialized subclass of it).
+ * @param parent the parent FONode
+ * @return the newly created FONode instance
+ */
public FONode make(FONode parent) {
return null;
}
diff --git a/src/java/org/apache/fop/fo/ElementMappingRegistry.java b/src/java/org/apache/fop/fo/ElementMappingRegistry.java
new file mode 100644
index 000000000..35224e7ae
--- /dev/null
+++ b/src/java/org/apache/fop/fo/ElementMappingRegistry.java
@@ -0,0 +1,175 @@
+/*
+ * Copyright 2006 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$ */
+
+package org.apache.fop.fo;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.fop.apps.FOPException;
+import org.apache.fop.apps.FOUserAgent;
+import org.apache.fop.fo.ElementMapping.Maker;
+import org.apache.fop.util.Service;
+import org.w3c.dom.DOMImplementation;
+import org.xml.sax.Locator;
+
+/**
+ * This class keeps track of all configured ElementMapping implementations which are responsible
+ * for properly handling all kinds of different XML namespaces.
+ */
+public class ElementMappingRegistry {
+
+ /** logging instance */
+ protected Log log = LogFactory.getLog(ElementMappingRegistry.class);
+
+ /**
+ * Table mapping element names to the makers of objects
+ * representing formatting objects.
+ */
+ protected Map fobjTable = new java.util.HashMap();
+
+ /**
+ * Map of mapped namespaces and their associated ElementMapping instances.
+ */
+ protected Map namespaces = new java.util.HashMap();
+
+ /**
+ * Main constructor. Adds all default element mapping as well as detects ElementMapping
+ * through the Service discovery.
+ * @param userAgent the user agent
+ */
+ public ElementMappingRegistry(FOUserAgent userAgent) {
+ // Add standard element mappings
+ setupDefaultMappings();
+
+ // add additional ElementMappings defined within FOUserAgent
+ List addlEMs = userAgent.getAdditionalElementMappings();
+
+ if (addlEMs != null) {
+ for (int i = 0; i < addlEMs.size(); i++) {
+ addElementMapping((ElementMapping) addlEMs.get(i));
+ }
+ }
+ }
+
+ /**
+ * Sets all the element and property list mappings to their default values.
+ */
+ private void setupDefaultMappings() {
+ addElementMapping("org.apache.fop.fo.FOElementMapping");
+ addElementMapping("org.apache.fop.fo.extensions.svg.SVGElementMapping");
+ addElementMapping("org.apache.fop.fo.extensions.svg.BatikExtensionElementMapping");
+ addElementMapping("org.apache.fop.fo.extensions.ExtensionElementMapping");
+ addElementMapping("org.apache.fop.render.ps.extensions.PSExtensionElementMapping");
+
+ // add mappings from available services
+ Iterator providers = Service.providers(ElementMapping.class);
+ if (providers != null) {
+ while (providers.hasNext()) {
+ String str = (String)providers.next();
+ try {
+ addElementMapping(str);
+ } catch (IllegalArgumentException e) {
+ log.warn("Error while adding element mapping", e);
+ }
+
+ }
+ }
+ }
+
+ /**
+ * Add the element mapping with the given class name.
+ * @param mappingClassName the class name representing the element mapping.
+ * @throws IllegalArgumentException if there was not such element mapping.
+ */
+ public void addElementMapping(String mappingClassName)
+ throws IllegalArgumentException {
+
+ try {
+ ElementMapping mapping
+ = (ElementMapping)Class.forName(mappingClassName).newInstance();
+ addElementMapping(mapping);
+ } catch (ClassNotFoundException e) {
+ throw new IllegalArgumentException("Could not find "
+ + mappingClassName);
+ } catch (InstantiationException e) {
+ throw new IllegalArgumentException("Could not instantiate "
+ + mappingClassName);
+ } catch (IllegalAccessException e) {
+ throw new IllegalArgumentException("Could not access "
+ + mappingClassName);
+ } catch (ClassCastException e) {
+ throw new IllegalArgumentException(mappingClassName
+ + " is not an ElementMapping");
+ }
+ }
+
+ private void addElementMapping(ElementMapping mapping) {
+ this.fobjTable.put(mapping.getNamespaceURI(), mapping.getTable());
+ this.namespaces.put(mapping.getNamespaceURI().intern(), mapping);
+ }
+
+ /**
+ * Finds the Maker used to create node objects of a particular type
+ * @param namespaceURI URI for the namespace of the element
+ * @param localName name of the Element
+ * @param locator the Locator instance for context information
+ * @return the ElementMapping.Maker that can create an FO object for this element
+ * @throws FOPException if a Maker could not be found for a bound namespace.
+ */
+ public Maker findFOMaker(String namespaceURI, String localName, Locator locator)
+ throws FOPException {
+ Map table = (Map)fobjTable.get(namespaceURI);
+ Maker fobjMaker = null;
+ if (table != null) {
+ fobjMaker = (ElementMapping.Maker)table.get(localName);
+ // try default
+ if (fobjMaker == null) {
+ fobjMaker = (ElementMapping.Maker)table.get(ElementMapping.DEFAULT);
+ }
+ }
+
+ if (fobjMaker == null) {
+ if (namespaces.containsKey(namespaceURI.intern())) {
+ throw new FOPException(FONode.errorText(locator)
+ + "No element mapping definition found for "
+ + FONode.getNodeString(namespaceURI, localName), locator);
+ } else {
+ log.warn("Unknown formatting object " + namespaceURI + "^" + localName);
+ fobjMaker = new UnknownXMLObj.Maker(namespaceURI);
+ }
+ }
+ return fobjMaker;
+ }
+
+ /**
+ * Tries to determine the DOMImplementation that is used to handled a particular namespace.
+ * The method may return null for namespaces that don't result in a DOM. It is mostly used
+ * in namespaces occurring in foreign objects.
+ * @param namespaceURI the namespace URI
+ * @return the handling DOMImplementation, or null if not applicable
+ */
+ public DOMImplementation getDOMImplementationForNamespace(String namespaceURI) {
+ ElementMapping mapping = (ElementMapping)this.namespaces.get(namespaceURI);
+ return mapping.getDOMImplementation();
+ }
+
+}
diff --git a/src/java/org/apache/fop/fo/FOTreeBuilder.java b/src/java/org/apache/fop/fo/FOTreeBuilder.java
index cc87fcca9..c0aa87a44 100644
--- a/src/java/org/apache/fop/fo/FOTreeBuilder.java
+++ b/src/java/org/apache/fop/fo/FOTreeBuilder.java
@@ -1,5 +1,5 @@
/*
- * Copyright 1999-2005 The Apache Software Foundation.
+ * Copyright 1999-2006 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.
@@ -19,10 +19,6 @@
package org.apache.fop.fo;
import java.io.OutputStream;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -30,7 +26,6 @@ import org.apache.fop.apps.FOPException;
import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.apps.FormattingResults;
import org.apache.fop.area.AreaTreeHandler;
-import org.apache.fop.util.Service;
import org.apache.fop.fo.ElementMapping.Maker;
import org.apache.fop.fo.pagination.Root;
import org.apache.fop.image.ImageFactory;
@@ -48,22 +43,12 @@ import org.xml.sax.helpers.DefaultHandler;
*/
public class FOTreeBuilder extends DefaultHandler {
- /**
- * Table mapping element names to the makers of objects
- * representing formatting objects.
- */
- protected Map fobjTable = new java.util.HashMap();
-
- /**
- * logging instance
- */
+ /** logging instance */
protected Log log = LogFactory.getLog(FOTreeBuilder.class);
- /**
- * Set of mapped namespaces.
- */
- protected Set namespaces = new java.util.HashSet();
-
+ /** The registry for ElementMapping instances */
+ protected ElementMappingRegistry elementMappingRegistry;
+
/**
* The root of the formatting object tree
*/
@@ -113,75 +98,7 @@ public class FOTreeBuilder extends DefaultHandler {
}
});
- // Add standard element mappings
- setupDefaultMappings();
-
- // add additional ElementMappings defined within FOUserAgent
- List addlEMs = foUserAgent.getAdditionalElementMappings();
-
- if (addlEMs != null) {
- for (int i = 0; i < addlEMs.size(); i++) {
- addElementMapping((ElementMapping) addlEMs.get(i));
- }
- }
- }
-
- /**
- * Sets all the element and property list mappings to their default values.
- *
- */
- private void setupDefaultMappings() {
- addElementMapping("org.apache.fop.fo.FOElementMapping");
- addElementMapping("org.apache.fop.fo.extensions.svg.SVGElementMapping");
- addElementMapping("org.apache.fop.fo.extensions.svg.BatikExtensionElementMapping");
- addElementMapping("org.apache.fop.fo.extensions.ExtensionElementMapping");
- addElementMapping("org.apache.fop.render.ps.extensions.PSExtensionElementMapping");
-
- // add mappings from available services
- Iterator providers = Service.providers(ElementMapping.class);
- if (providers != null) {
- while (providers.hasNext()) {
- String str = (String)providers.next();
- try {
- addElementMapping(str);
- } catch (IllegalArgumentException e) {
- log.warn("Error while adding element mapping", e);
- }
-
- }
- }
- }
-
- /**
- * Add the element mapping with the given class name.
- * @param mappingClassName the class name representing the element mapping.
- * @throws IllegalArgumentException if there was not such element mapping.
- */
- public void addElementMapping(String mappingClassName)
- throws IllegalArgumentException {
-
- try {
- ElementMapping mapping
- = (ElementMapping)Class.forName(mappingClassName).newInstance();
- addElementMapping(mapping);
- } catch (ClassNotFoundException e) {
- throw new IllegalArgumentException("Could not find "
- + mappingClassName);
- } catch (InstantiationException e) {
- throw new IllegalArgumentException("Could not instantiate "
- + mappingClassName);
- } catch (IllegalAccessException e) {
- throw new IllegalArgumentException("Could not access "
- + mappingClassName);
- } catch (ClassCastException e) {
- throw new IllegalArgumentException(mappingClassName
- + " is not an ElementMapping");
- }
- }
-
- private void addElementMapping(ElementMapping mapping) {
- this.fobjTable.put(mapping.getNamespaceURI(), mapping.getTable());
- this.namespaces.add(mapping.getNamespaceURI().intern());
+ this.elementMappingRegistry = new ElementMappingRegistry(foUserAgent);
}
/**
@@ -340,27 +257,7 @@ public class FOTreeBuilder extends DefaultHandler {
* @throws FOPException if a Maker could not be found for a bound namespace.
*/
private Maker findFOMaker(String namespaceURI, String localName) throws FOPException {
- Map table = (Map)fobjTable.get(namespaceURI);
- Maker fobjMaker = null;
- if (table != null) {
- fobjMaker = (ElementMapping.Maker)table.get(localName);
- // try default
- if (fobjMaker == null) {
- fobjMaker = (ElementMapping.Maker)table.get(ElementMapping.DEFAULT);
- }
- }
-
- if (fobjMaker == null) {
- if (namespaces.contains(namespaceURI.intern())) {
- throw new FOPException(FONode.errorText(locator)
- + "No element mapping definition found for "
- + FONode.getNodeString(namespaceURI, localName), locator);
- } else {
- log.warn("Unknown formatting object " + namespaceURI + "^" + localName);
- fobjMaker = new UnknownXMLObj.Maker(namespaceURI);
- }
- }
- return fobjMaker;
+ return elementMappingRegistry.findFOMaker(namespaceURI, localName, locator);
}
/** @see org.xml.sax.ErrorHandler#warning(org.xml.sax.SAXParseException) */
diff --git a/src/java/org/apache/fop/fo/extensions/svg/BatikExtensionElementMapping.java b/src/java/org/apache/fop/fo/extensions/svg/BatikExtensionElementMapping.java
index 7b34d6c01..0fce5b8dd 100644
--- a/src/java/org/apache/fop/fo/extensions/svg/BatikExtensionElementMapping.java
+++ b/src/java/org/apache/fop/fo/extensions/svg/BatikExtensionElementMapping.java
@@ -1,5 +1,5 @@
/*
- * Copyright 1999-2004 The Apache Software Foundation.
+ * Copyright 1999-2004,2006 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.
@@ -24,19 +24,29 @@ import javax.xml.parsers.SAXParserFactory;
import org.apache.batik.util.XMLResourceDescriptor;
import org.apache.fop.fo.ElementMapping;
import org.apache.fop.fo.FONode;
+import org.w3c.dom.DOMImplementation;
/**
* This Element Mapping is for Batik SVG Extension elements
* of the http://xml.apache.org/batik/ext namespace.
*/
public class BatikExtensionElementMapping extends ElementMapping {
- public static String URI = "http://xml.apache.org/batik/ext";
+
+ /** Namespace URI for Batik extension elements */
+ public static final String URI = "http://xml.apache.org/batik/ext";
+
private boolean batikAvail = true;
+ /** Main constructor. */
public BatikExtensionElementMapping() {
namespaceURI = URI;
}
+ /** @see org.apache.fop.fo.ElementMapping#getDOMImplementation() */
+ public DOMImplementation getDOMImplementation() {
+ return null; //no DOMImplementation necessary here
+ }
+
/**
* Returns the fully qualified classname of an XML parser for
* Batik classes that apparently need it (error messages, perhaps)
@@ -83,4 +93,5 @@ public class BatikExtensionElementMapping extends ElementMapping {
return new SVGElement(parent);
}
}
+
}
diff --git a/src/java/org/apache/fop/fo/extensions/svg/SVGElementMapping.java b/src/java/org/apache/fop/fo/extensions/svg/SVGElementMapping.java
index 6b477bf46..78fab53f8 100644
--- a/src/java/org/apache/fop/fo/extensions/svg/SVGElementMapping.java
+++ b/src/java/org/apache/fop/fo/extensions/svg/SVGElementMapping.java
@@ -1,5 +1,5 @@
/*
- * Copyright 1999-2004 The Apache Software Foundation.
+ * Copyright 1999-2004,2006 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.
@@ -26,6 +26,7 @@ import org.apache.fop.fo.ElementMapping;
import org.apache.batik.util.XMLResourceDescriptor;
import org.apache.batik.dom.svg.SVGDOMImplementation;
+import org.w3c.dom.DOMImplementation;
/**
* Setup the SVG element mapping.
@@ -33,19 +34,28 @@ import org.apache.batik.dom.svg.SVGDOMImplementation;
* that create the SVG Document.
*/
public class SVGElementMapping extends ElementMapping {
- public static String URI = SVGDOMImplementation.SVG_NAMESPACE_URI;
- private boolean batik = true;
+
+ /** the SVG namespace */
+ public static final String URI = SVGDOMImplementation.SVG_NAMESPACE_URI;
+
+ private boolean batikAvailable = true;
+ /** Main constructor. */
public SVGElementMapping() {
namespaceURI = URI;
}
+ /** @see org.apache.fop.fo.ElementMapping#getDOMImplementation() */
+ public DOMImplementation getDOMImplementation() {
+ return SVGDOMImplementation.getDOMImplementation();
+ }
+
/**
* Returns the fully qualified classname of an XML parser for
* Batik classes that apparently need it (error messages, perhaps)
* @return an XML parser classname
*/
- private final String getAParserClassName() {
+ private String getAParserClassName() {
try {
SAXParserFactory factory = SAXParserFactory.newInstance();
return factory.newSAXParser().getXMLReader().getClass().getName();
@@ -54,8 +64,9 @@ public class SVGElementMapping extends ElementMapping {
}
}
+ /** @see org.apache.fop.fo.ElementMapping#initialize() */
protected void initialize() {
- if (foObjs == null && batik == true) {
+ if (foObjs == null && batikAvailable) {
// this sets the parser that will be used
// by default (SVGBrokenLinkProvider)
// normally the user agent value is used
@@ -69,7 +80,7 @@ public class SVGElementMapping extends ElementMapping {
} catch (Throwable t) {
// if the classes are not available
// the DISPLAY is not checked
- batik = false;
+ batikAvailable = false;
}
}
}
@@ -85,4 +96,5 @@ public class SVGElementMapping extends ElementMapping {
return new SVGElement(parent);
}
}
+
}
diff --git a/src/java/org/apache/fop/fonts/LazyFont.java b/src/java/org/apache/fop/fonts/LazyFont.java
index 867158e6b..f8d22f3bb 100644
--- a/src/java/org/apache/fop/fonts/LazyFont.java
+++ b/src/java/org/apache/fop/fonts/LazyFont.java
@@ -165,6 +165,7 @@ public class LazyFont extends Typeface implements FontDescriptor {
* @see org.apache.fop.fonts.Typeface#isMultiByte()
*/
public boolean isMultiByte() {
+ load(true);
return realFont.isMultiByte();
}
diff --git a/src/java/org/apache/fop/render/XMLHandlerRegistry.java b/src/java/org/apache/fop/render/XMLHandlerRegistry.java
index e033c2d4e..1603f74ec 100644
--- a/src/java/org/apache/fop/render/XMLHandlerRegistry.java
+++ b/src/java/org/apache/fop/render/XMLHandlerRegistry.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2005 The Apache Software Foundation.
+ * Copyright 2005-2006 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.
@@ -117,9 +117,16 @@ public class XMLHandlerRegistry {
XMLHandler handler;
List lst = (List)handlers.get(ns);
- if (lst == null) {
+ handler = getXMLHandler(renderer, lst);
+ if (handler == null) {
lst = (List)handlers.get(XMLHandler.HANDLE_ALL);
+ handler = getXMLHandler(renderer, lst);
}
+ return handler;
+ }
+
+ private XMLHandler getXMLHandler(Renderer renderer, List lst) {
+ XMLHandler handler;
if (lst != null) {
for (int i = 0, c = lst.size(); i < c; i++) {
//TODO Maybe add priorities later
@@ -132,7 +139,6 @@ public class XMLHandlerRegistry {
return null; //No handler found
}
-
/**
* Discovers XMLHandler implementations through the classpath and dynamically
* registers them.
diff --git a/src/java/org/apache/fop/render/xml/XMLRenderer.java b/src/java/org/apache/fop/render/xml/XMLRenderer.java
index 2f7da2a08..1b9afc566 100644
--- a/src/java/org/apache/fop/render/xml/XMLRenderer.java
+++ b/src/java/org/apache/fop/render/xml/XMLRenderer.java
@@ -40,6 +40,7 @@ import org.xml.sax.helpers.AttributesImpl;
// FOP
import org.apache.fop.render.PrintRenderer;
+import org.apache.fop.render.Renderer;
import org.apache.fop.render.RendererContext;
import org.apache.fop.render.XMLHandler;
import org.apache.fop.apps.FOUserAgent;
@@ -60,6 +61,7 @@ import org.apache.fop.area.RegionReference;
import org.apache.fop.area.RegionViewport;
import org.apache.fop.area.Span;
import org.apache.fop.area.Trait;
+import org.apache.fop.area.Trait.Background;
import org.apache.fop.area.inline.Container;
import org.apache.fop.area.inline.ForeignObject;
import org.apache.fop.area.inline.Image;
@@ -72,6 +74,8 @@ import org.apache.fop.area.inline.Viewport;
import org.apache.fop.area.inline.TextArea;
import org.apache.fop.area.inline.SpaceArea;
import org.apache.fop.area.inline.WordArea;
+import org.apache.fop.fo.Constants;
+import org.apache.fop.fonts.FontInfo;
import org.apache.fop.fonts.FontSetup;
import org.apache.fop.fonts.FontTriplet;
@@ -99,6 +103,9 @@ public class XMLRenderer extends PrintRenderer {
private boolean startedSequence = false;
private RendererContext context;
+ /** If not null, the XMLRenderer will mimic another renderer by using its font setup. */
+ protected Renderer mimic;
+
/** TransformerHandler that the generated XML is written to */
protected TransformerHandler handler;
@@ -137,10 +144,26 @@ public class XMLRenderer extends PrintRenderer {
public void setUserAgent(FOUserAgent agent) {
super.setUserAgent(agent);
- //
- //userAgent.addExtensionHandler();
- XMLHandler handler = new XMLXMLHandler();
- userAgent.getXMLHandlerRegistry().addXMLHandler(handler);
+ XMLHandler xmlHandler = new XMLXMLHandler();
+ userAgent.getXMLHandlerRegistry().addXMLHandler(xmlHandler);
+ }
+
+ /**
+ * Call this method to make the XMLRenderer mimic a different renderer by using its font
+ * setup. This is useful when working with the intermediate format parser.
+ * @param renderer the renderer to mimic
+ */
+ public void mimicRenderer(Renderer renderer) {
+ this.mimic = renderer;
+ }
+
+ /** @see org.apache.fop.render.PrintRenderer#setupFontInfo(org.apache.fop.fonts.FontInfo) */
+ public void setupFontInfo(FontInfo inFontInfo) {
+ if (mimic != null) {
+ mimic.setupFontInfo(inFontInfo);
+ } else {
+ super.setupFontInfo(inFontInfo);
+ }
}
/**
@@ -280,6 +303,7 @@ public class XMLRenderer extends PrintRenderer {
while (iter.hasNext()) {
Map.Entry traitEntry = (Map.Entry) iter.next();
String name = Trait.getTraitName(traitEntry.getKey());
+ Class clazz = Trait.getTraitClass(traitEntry.getKey());
if ("break-before".equals(name) || "break-after".equals(name)) {
continue;
}
@@ -289,6 +313,38 @@ public class XMLRenderer extends PrintRenderer {
addAttribute("font-name", triplet.getName());
addAttribute("font-style", triplet.getStyle());
addAttribute("font-weight", triplet.getWeight());
+ } else if (clazz.equals(Background.class)) {
+ Background bkg = (Background)value;
+ //TODO Remove the following line (makes changes in the test checks necessary)
+ addAttribute(name, bkg.toString());
+ if (bkg.getColor() != null) {
+ addAttribute("bkg-color", bkg.getColor().toString());
+ }
+ if (bkg.getURL() != null) {
+ addAttribute("bkg-img", bkg.getURL());
+ String repString;
+ int repeat = bkg.getRepeat();
+ switch (repeat) {
+ case Constants.EN_REPEAT:
+ repString = "repeat";
+ break;
+ case Constants.EN_REPEATX:
+ repString = "repeat-x";
+ break;
+ case Constants.EN_REPEATY:
+ repString = "repeat-y";
+ break;
+ case Constants.EN_NOREPEAT:
+ repString = "no-repeat";
+ break;
+ default:
+ throw new IllegalStateException(
+ "Illegal value for repeat encountered: " + repeat);
+ }
+ addAttribute("bkg-repeat", repString);
+ addAttribute("bkg-horz-offset", bkg.getHoriz());
+ addAttribute("bkg-vert-offset", bkg.getVertical());
+ }
} else {
addAttribute(name, value.toString());
}
@@ -404,6 +460,7 @@ public class XMLRenderer extends PrintRenderer {
atts.clear();
addAreaAttributes(region);
addTraitAttributes(region);
+ addAttribute("name", region.getRegionName());
addAttribute("ctm", region.getCTM().toString());
if (region.getRegionClass() == FO_REGION_BEFORE) {
startElement("regionBefore", atts);
@@ -414,8 +471,13 @@ public class XMLRenderer extends PrintRenderer {
renderRegion(region);
endElement("regionStart");
} else if (region.getRegionClass() == FO_REGION_BODY) {
+ BodyRegion body = (BodyRegion)region;
+ if (body.getColumnCount() != 1) {
+ addAttribute("columnGap", body.getColumnGap());
+ addAttribute("columnCount", body.getColumnCount());
+ }
startElement("regionBody", atts);
- renderBodyRegion((BodyRegion) region);
+ renderBodyRegion(body);
endElement("regionBody");
} else if (region.getRegionClass() == FO_REGION_END) {
startElement("regionEnd", atts);
@@ -465,7 +527,9 @@ public class XMLRenderer extends PrintRenderer {
atts.clear();
addAreaAttributes(mr);
addTraitAttributes(mr);
- addAttribute("columnGap", mr.getColumnGap());
+ if (mr.getColumnCount() != 1) {
+ addAttribute("columnGap", mr.getColumnGap());
+ }
startElement("mainReference", atts);
Span span = null;
@@ -473,6 +537,9 @@ public class XMLRenderer extends PrintRenderer {
for (int count = 0; count < spans.size(); count++) {
span = (Span) spans.get(count);
atts.clear();
+ if (span.getColumnCount() != 1) {
+ addAttribute("columnCount", span.getColumnCount());
+ }
addAreaAttributes(span);
addTraitAttributes(span);
startElement("span", atts);
@@ -506,14 +573,12 @@ public class XMLRenderer extends PrintRenderer {
atts.clear();
addAreaAttributes(block);
addTraitAttributes(block);
+ int positioning = block.getPositioning();
if (block instanceof BlockViewport) {
BlockViewport bvp = (BlockViewport)block;
boolean abspos = false;
- if (bvp.getPositioning() == Block.ABSOLUTE) {
- addAttribute("positioning", "absolute");
- abspos = true;
- } else if (bvp.getPositioning() == Block.FIXED) {
- addAttribute("positioning", "fixed");
+ if (bvp.getPositioning() == Block.ABSOLUTE
+ || bvp.getPositioning() == Block.FIXED) {
abspos = true;
}
if (abspos) {
@@ -525,9 +590,6 @@ public class XMLRenderer extends PrintRenderer {
addAttribute("clipped", "true");
}
} else {
- if (block.getPositioning() == Block.RELATIVE) {
- addAttribute("positioning", "relative");
- }
if (block.getXOffset() != 0) {
addAttribute("left-offset", block.getXOffset());
}
@@ -535,6 +597,18 @@ public class XMLRenderer extends PrintRenderer {
addAttribute("top-offset", block.getYOffset());
}
}
+ switch (positioning) {
+ case Block.RELATIVE:
+ addAttribute("positioning", "relative");
+ break;
+ case Block.ABSOLUTE:
+ addAttribute("positioning", "absolute");
+ break;
+ case Block.FIXED:
+ addAttribute("positioning", "fixed");
+ break;
+ default: //nop
+ }
startElement("block", atts);
super.renderBlock(block);
endElement("block");
@@ -563,6 +637,10 @@ public class XMLRenderer extends PrintRenderer {
addAreaAttributes(viewport);
addTraitAttributes(viewport);
addAttribute("offset", viewport.getOffset());
+ addAttribute("pos", viewport.getContentPosition());
+ if (viewport.getClip()) {
+ addAttribute("clip", Boolean.toString(viewport.getClip()));
+ }
startElement("viewport", atts);
super.renderViewport(viewport);
endElement("viewport");
@@ -576,7 +654,7 @@ public class XMLRenderer extends PrintRenderer {
addAreaAttributes(image);
addTraitAttributes(image);
addAttribute("url", image.getURL());
- addAttribute("pos", pos);
+ //addAttribute("pos", pos);
startElement("image", atts);
endElement("image");
}
@@ -600,10 +678,10 @@ public class XMLRenderer extends PrintRenderer {
atts.clear();
addAreaAttributes(fo);
addTraitAttributes(fo);
- addAttribute("pos", pos);
+ String ns = fo.getNameSpace();
+ addAttribute("ns", ns);
startElement("foreignObject", atts);
Document doc = fo.getDocument();
- String ns = fo.getNameSpace();
context.setProperty(XMLXMLHandler.HANDLER, handler);
renderXML(context, doc, ns);
endElement("foreignObject");
@@ -709,36 +787,11 @@ public class XMLRenderer extends PrintRenderer {
* @see org.apache.fop.render.AbstractRenderer#renderLeader(Leader)
*/
protected void renderLeader(Leader area) {
- String style = "solid";
- switch (area.getRuleStyle()) {
- case EN_DOTTED:
- style = "dotted";
- break;
- case EN_DASHED:
- style = "dashed";
- break;
- case EN_SOLID:
- break;
- case EN_DOUBLE:
- style = "double";
- break;
- case EN_GROOVE:
- style = "groove";
- break;
- case EN_RIDGE:
- style = "ridge";
- break;
- case EN_NONE:
- style = "none";
- break;
- default:
- style = "--NYI--";
- }
atts.clear();
addAreaAttributes(area);
addTraitAttributes(area);
addAttribute("offset", area.getOffset());
- addAttribute("ruleStyle", style);
+ addAttribute("ruleStyle", area.getRuleStyleAsString());
addAttribute("ruleThickness", area.getRuleThickness());
startElement("leader", atts);
endElement("leader");
diff --git a/src/java/org/apache/fop/traits/BorderProps.java b/src/java/org/apache/fop/traits/BorderProps.java
index 8de33920f..32722cc8a 100644
--- a/src/java/org/apache/fop/traits/BorderProps.java
+++ b/src/java/org/apache/fop/traits/BorderProps.java
@@ -1,5 +1,5 @@
/*
- * Copyright 1999-2005 The Apache Software Foundation.
+ * Copyright 1999-2006 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.
@@ -21,8 +21,10 @@ package org.apache.fop.traits;
import org.apache.fop.area.Trait;
import org.apache.fop.datatypes.ColorType;
import org.apache.fop.fo.Constants;
+import org.apache.fop.fonts.FontTriplet;
import java.io.Serializable;
+import java.util.StringTokenizer;
/**
* Border properties.
@@ -61,6 +63,17 @@ public class BorderProps implements Serializable {
}
/**
+ * Constructs a new BorderProps instance.
+ * @param style border style (one of the XSL enum values for border style)
+ * @param width border width
+ * @param color border color
+ * @param mode border mode ((one of SEPARATE, COLLAPSE_INNER and COLLAPSE_OUTER)
+ */
+ public BorderProps(String style, int width, ColorType color, int mode) {
+ this(getConstantForStyle(style), width, color, mode);
+ }
+
+ /**
* @param bp the border properties or null
* @return the effective width of the clipped part of the border
*/
@@ -88,6 +101,83 @@ public class BorderProps implements Serializable {
}
}
+ private static int getConstantForStyle(String style) {
+ if ("none".equalsIgnoreCase(style)) {
+ return Constants.EN_NONE;
+ } else if ("hidden".equalsIgnoreCase(style)) {
+ return Constants.EN_HIDDEN;
+ } else if ("dotted".equalsIgnoreCase(style)) {
+ return Constants.EN_DOTTED;
+ } else if ("dashed".equalsIgnoreCase(style)) {
+ return Constants.EN_DASHED;
+ } else if ("solid".equalsIgnoreCase(style)) {
+ return Constants.EN_SOLID;
+ } else if ("double".equalsIgnoreCase(style)) {
+ return Constants.EN_DOUBLE;
+ } else if ("groove".equalsIgnoreCase(style)) {
+ return Constants.EN_GROOVE;
+ } else if ("ridge".equalsIgnoreCase(style)) {
+ return Constants.EN_RIDGE;
+ } else if ("inset".equalsIgnoreCase(style)) {
+ return Constants.EN_INSET;
+ } else if ("outset".equalsIgnoreCase(style)) {
+ return Constants.EN_OUTSET;
+ } else {
+ throw new IllegalStateException("Illegal border style: " + style);
+ }
+ }
+
+ /** @see java.lang.Object#hashCode() */
+ public int hashCode() {
+ return toString().hashCode();
+ }
+
+ /** @see java.lang.Object#equals(java.lang.Object) */
+ public boolean equals(Object obj) {
+ if (obj == null) {
+ return false;
+ } else if (obj == this) {
+ return true;
+ } else {
+ if (obj instanceof BorderProps) {
+ BorderProps other = (BorderProps)obj;
+ return (style == other.style)
+ && color.equals(other.color)
+ && width == other.width
+ && mode == other.mode;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Returns a BorderProps represtation of a string of the format as written by
+ * BorderProps.toString().
+ * @param s the string
+ * @return a BorderProps instance
+ */
+ public static BorderProps valueOf(String s) {
+ if (s.startsWith("(") && s.endsWith(")")) {
+ s = s.substring(1, s.length() - 1);
+ StringTokenizer st = new StringTokenizer(s, ",");
+ String style = st.nextToken();
+ String color = st.nextToken();
+ int width = Integer.parseInt(st.nextToken());
+ int mode = SEPARATE;
+ if (st.hasMoreTokens()) {
+ String ms = st.nextToken();
+ if ("collapse-inner".equalsIgnoreCase(ms)) {
+ mode = COLLAPSE_INNER;
+ } else if ("collapse-outer".equalsIgnoreCase(ms)) {
+ mode = COLLAPSE_OUTER;
+ }
+ }
+ return new BorderProps(style, width, Trait.Color.valueOf(color), mode);
+ } else {
+ throw new IllegalArgumentException("BorderProps must be surrounded by parentheses");
+ }
+ }
+
/** @see java.lang.Object#toString() */
public String toString() {
StringBuffer sbuf = new StringBuffer();
@@ -108,4 +198,5 @@ public class BorderProps implements Serializable {
sbuf.append(')');
return sbuf.toString();
}
+
}
diff --git a/src/java/org/apache/fop/util/DefaultErrorListener.java b/src/java/org/apache/fop/util/DefaultErrorListener.java
new file mode 100644
index 000000000..5e1a9cc37
--- /dev/null
+++ b/src/java/org/apache/fop/util/DefaultErrorListener.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2006 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$ */
+
+package org.apache.fop.util;
+
+import javax.xml.transform.ErrorListener;
+import javax.xml.transform.TransformerException;
+
+import org.apache.commons.logging.Log;
+
+/**
+ * Standard ErrorListener implementation for in-FOP use. Some Xalan-J versions don't properly
+ * re-throw exceptions.
+ */
+public class DefaultErrorListener implements ErrorListener {
+
+ private Log log;
+
+ /**
+ * Main constructor
+ * @param log the log instance to send log events to
+ */
+ public DefaultErrorListener(Log log) {
+ this.log = log;
+ }
+
+ /**
+ * @see javax.xml.transform.ErrorListener#warning(javax.xml.transform.TransformerException)
+ */
+ public void warning(TransformerException exc) {
+ log.warn(exc.toString());
+ }
+
+ /**
+ * @see javax.xml.transform.ErrorListener#error(javax.xml.transform.TransformerException)
+ */
+ public void error(TransformerException exc) throws TransformerException {
+ throw exc;
+ }
+
+ /**
+ * @see javax.xml.transform.ErrorListener#fatalError(javax.xml.transform.TransformerException)
+ */
+ public void fatalError(TransformerException exc)
+ throws TransformerException {
+ throw exc;
+ }
+
+} \ No newline at end of file