org.apache.fop.render.intermediate.IFParser Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of org.apache.fop Show documentation
Show all versions of org.apache.fop Show documentation
The core maven build properties
The newest version!
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* $Id: IFParser.java 1875656 2020-03-25 16:36:47Z ssteiner $ */
package org.apache.fop.render.intermediate;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.geom.AffineTransform;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.sax.SAXResult;
import javax.xml.transform.sax.SAXTransformerFactory;
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.AttributesImpl;
import org.xml.sax.helpers.DefaultHandler;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.xmlgraphics.util.QName;
import org.apache.fop.accessibility.AccessibilityEventProducer;
import org.apache.fop.accessibility.StructureTreeElement;
import org.apache.fop.accessibility.StructureTreeEventHandler;
import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.fo.ElementMapping;
import org.apache.fop.fo.ElementMappingRegistry;
import org.apache.fop.fo.expr.PropertyException;
import org.apache.fop.fo.extensions.InternalElementMapping;
import org.apache.fop.render.intermediate.extensions.DocumentNavigationExtensionConstants;
import org.apache.fop.render.intermediate.extensions.DocumentNavigationHandler;
import org.apache.fop.traits.BorderProps;
import org.apache.fop.traits.RuleStyle;
import org.apache.fop.util.ColorUtil;
import org.apache.fop.util.ContentHandlerFactory;
import org.apache.fop.util.ContentHandlerFactoryRegistry;
import org.apache.fop.util.DOMBuilderContentHandlerFactory;
import org.apache.fop.util.DefaultErrorListener;
import org.apache.fop.util.LanguageTags;
import org.apache.fop.util.XMLUtil;
/**
* This is a parser for the intermediate format XML which converts the intermediate file into
* {@link IFPainter} events.
*/
public class IFParser implements IFConstants {
/** Logger instance */
protected static final Log log = LogFactory.getLog(IFParser.class);
private static SAXTransformerFactory tFactory
= (SAXTransformerFactory)SAXTransformerFactory.newInstance();
private static Set handledNamespaces = new java.util.HashSet();
static {
handledNamespaces.add(XMLNS_NAMESPACE_URI);
handledNamespaces.add(XML_NAMESPACE);
handledNamespaces.add(NAMESPACE);
handledNamespaces.add(XLINK_NAMESPACE);
}
/**
* Parses an intermediate file and paints it.
* @param src the Source instance pointing to the intermediate file
* @param documentHandler the intermediate format document handler used to process the IF events
* @param userAgent the user agent
* @throws TransformerException if an error occurs while parsing the area tree XML
* @throws IFException if an IF-related error occurs inside the target document handler
*/
public void parse(Source src, IFDocumentHandler documentHandler, FOUserAgent userAgent)
throws TransformerException, IFException {
try {
Transformer transformer = tFactory.newTransformer();
transformer.setErrorListener(new DefaultErrorListener(log));
SAXResult res = new SAXResult(getContentHandler(documentHandler, userAgent));
transformer.transform(src, res);
} catch (TransformerException te) {
Throwable cause = te.getCause();
//Unpack original IFException if applicable
if (cause instanceof SAXException) {
SAXException se = (SAXException) cause;
cause = se.getCause();
if (cause instanceof IFException) {
throw (IFException) cause;
}
} else if (cause instanceof IFException) {
throw (IFException) cause;
}
throw te;
}
}
/**
* 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 documentHandler the intermediate format document handler used to process the IF events
* @param userAgent the user agent
* @return the ContentHandler instance to receive the SAX stream from the area tree XML
*/
public ContentHandler getContentHandler(IFDocumentHandler documentHandler,
FOUserAgent userAgent) {
ElementMappingRegistry elementMappingRegistry
= userAgent.getElementMappingRegistry();
return new Handler(documentHandler, userAgent, elementMappingRegistry);
}
private static class Handler extends DefaultHandler {
private Map elementHandlers = new HashMap();
private IFDocumentHandler documentHandler;
private IFPainter painter;
private FOUserAgent userAgent;
private ElementMappingRegistry elementMappingRegistry;
private Attributes lastAttributes;
private StringBuffer content = new StringBuffer();
private boolean ignoreCharacters = true;
//private Stack delegateStack = new Stack();
private int delegateDepth;
private ContentHandler delegate;
private boolean inForeignObject;
private Document foreignObject;
private ContentHandler navParser;
private StructureTreeHandler structureTreeHandler;
private Attributes pageSequenceAttributes;
private Map structureTreeElements
= new HashMap();
private class StructureTreeHandler extends DefaultHandler {
protected final StructureTreeEventHandler structureTreeEventHandler;
StructureTreeHandler(StructureTreeEventHandler structureTreeEventHandler) {
this.structureTreeEventHandler = structureTreeEventHandler;
}
void startStructureTree(String type) {
}
@Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
if (!"structure-tree".equals(localName)) {
if (localName.equals("marked-content")) {
localName = "#PCDATA";
}
StructureTreeElement parent = getStructureTreeElement(attributes);
String structID = attributes.getValue(InternalElementMapping.URI,
InternalElementMapping.STRUCT_ID);
if (structID == null) {
structureTreeEventHandler.startNode(localName, attributes, parent);
} else if (localName.equals("external-graphic")
|| localName.equals("instream-foreign-object")) {
StructureTreeElement structureTreeElement
= structureTreeEventHandler.startImageNode(localName, attributes, parent);
structureTreeElements.put(structID, structureTreeElement);
} else {
StructureTreeElement structureTreeElement = structureTreeEventHandler
.startReferencedNode(localName, attributes, parent);
structureTreeElements.put(structID, structureTreeElement);
}
}
}
@Override
public void endElement(String uri, String localName, String arqNameg2)
throws SAXException {
if (!"structure-tree".equals(localName)) {
structureTreeEventHandler.endNode(localName);
}
}
}
private class MainStructureTreeHandler extends StructureTreeHandler {
private final Locale pageSequenceLanguage;
MainStructureTreeHandler(StructureTreeEventHandler structureTreeEventHandler,
Locale pageSequenceLanguage) throws SAXException {
super(structureTreeEventHandler);
this.pageSequenceLanguage = pageSequenceLanguage;
}
@Override
void startStructureTree(String type) {
structureTreeEventHandler.startPageSequence(pageSequenceLanguage, type);
}
public void endDocument() throws SAXException {
startIFElement(EL_PAGE_SEQUENCE, pageSequenceAttributes);
pageSequenceAttributes = null;
}
}
public Handler(IFDocumentHandler documentHandler, FOUserAgent userAgent,
ElementMappingRegistry elementMappingRegistry) {
this.documentHandler = documentHandler;
this.userAgent = userAgent;
this.elementMappingRegistry = elementMappingRegistry;
elementHandlers.put(EL_DOCUMENT, new DocumentHandler());
elementHandlers.put(EL_HEADER, new DocumentHeaderHandler());
elementHandlers.put(EL_LOCALE, new LocaleHandler());
elementHandlers.put(EL_TRAILER, new DocumentTrailerHandler());
elementHandlers.put(EL_PAGE_SEQUENCE, new PageSequenceHandler());
elementHandlers.put(EL_PAGE, new PageHandler());
elementHandlers.put(EL_PAGE_HEADER, new PageHeaderHandler());
elementHandlers.put(EL_PAGE_CONTENT, new PageContentHandler());
elementHandlers.put(EL_PAGE_TRAILER, new PageTrailerHandler());
//Page content
elementHandlers.put(EL_VIEWPORT, new ViewportHandler());
elementHandlers.put(EL_GROUP, new GroupHandler());
elementHandlers.put(EL_ID, new IDHandler());
elementHandlers.put(EL_FONT, new FontHandler());
elementHandlers.put(EL_TEXT, new TextHandler());
elementHandlers.put(EL_CLIP_RECT, new ClipRectHandler());
elementHandlers.put(EL_RECT, new RectHandler());
elementHandlers.put(EL_LINE, new LineHandler());
elementHandlers.put(EL_BORDER_RECT, new BorderRectHandler());
elementHandlers.put(EL_IMAGE, new ImageHandler());
}
private void establishForeignAttributes(Map foreignAttributes) {
documentHandler.getContext().setForeignAttributes(foreignAttributes);
}
private void resetForeignAttributes() {
documentHandler.getContext().resetForeignAttributes();
}
/** {@inheritDoc} */
public void startElement(String uri, String localName, String qName, Attributes attributes)
throws SAXException {
if (delegate != null) {
delegateDepth++;
delegate.startElement(uri, localName, qName, attributes);
} else {
boolean handled = true;
if (NAMESPACE.equals(uri)) {
if (localName.equals(EL_PAGE_SEQUENCE) && userAgent.isAccessibilityEnabled()) {
pageSequenceAttributes = new AttributesImpl(attributes);
Locale language = getLanguage(attributes);
structureTreeHandler = new MainStructureTreeHandler(
userAgent.getStructureTreeEventHandler(), language);
} else if (localName.equals(EL_STRUCTURE_TREE)) {
if (userAgent.isAccessibilityEnabled()) {
String type = attributes.getValue("type");
structureTreeHandler.startStructureTree(type);
delegate = structureTreeHandler;
} else {
/* Delegate to a handler that does nothing */
delegate = new DefaultHandler();
}
delegateDepth++;
delegate.startDocument();
delegate.startElement(uri, localName, qName, attributes);
} else {
if (pageSequenceAttributes != null) {
/*
* This means that no structure-element tag was
* found in the XML, otherwise a
* StructureTreeBuilderWrapper object would have
* been created, which would have reset the
* pageSequenceAttributes field.
*/
AccessibilityEventProducer.Provider
.get(userAgent.getEventBroadcaster())
.noStructureTreeInXML(this);
}
handled = startIFElement(localName, attributes);
}
} else if (DocumentNavigationExtensionConstants.NAMESPACE.equals(uri)) {
if (this.navParser == null) {
this.navParser = new DocumentNavigationHandler(
this.documentHandler.getDocumentNavigationHandler(),
structureTreeElements);
}
delegate = this.navParser;
delegateDepth++;
delegate.startDocument();
delegate.startElement(uri, localName, qName, attributes);
} else {
ContentHandlerFactoryRegistry registry
= userAgent.getContentHandlerFactoryRegistry();
ContentHandlerFactory factory = registry.getFactory(uri);
if (factory == null) {
DOMImplementation domImplementation
= elementMappingRegistry.getDOMImplementationForNamespace(uri);
if (domImplementation == null) {
domImplementation = ElementMapping.getDefaultDOMImplementation();
/*
throw new SAXException("No DOMImplementation could be"
+ " identified to handle namespace: " + uri);
*/
}
factory = new DOMBuilderContentHandlerFactory(uri, domImplementation);
}
delegate = factory.createContentHandler();
delegateDepth++;
delegate.startDocument();
delegate.startElement(uri, localName, qName, attributes);
}
if (!handled) {
if (uri == null || uri.length() == 0) {
throw new SAXException("Unhandled element " + localName
+ " in namespace: " + uri);
} else {
log.warn("Unhandled element " + localName
+ " in namespace: " + uri);
}
}
}
}
private static Locale getLanguage(Attributes attributes) {
String xmllang = attributes.getValue(XML_NAMESPACE, "lang");
return (xmllang == null) ? null : LanguageTags.toLocale(xmllang);
}
private boolean startIFElement(String localName, Attributes attributes)
throws SAXException {
lastAttributes = new AttributesImpl(attributes);
ElementHandler elementHandler = elementHandlers.get(localName);
content.setLength(0);
ignoreCharacters = true;
if (elementHandler != null) {
ignoreCharacters = elementHandler.ignoreCharacters();
try {
elementHandler.startElement(attributes);
} catch (IFException ife) {
handleIFException(ife);
}
return true;
} else {
return false;
}
}
private void handleIFException(IFException ife) throws SAXException {
Throwable cause = ife.getCause();
if (cause instanceof SAXException) {
//unwrap
throw (SAXException) cause;
} else {
//wrap
throw new SAXException(ife);
}
}
/** {@inheritDoc} */
public void endElement(String uri, String localName, String qName) throws SAXException {
if (delegate != null) {
delegate.endElement(uri, localName, qName);
delegateDepth--;
if (delegateDepth == 0) {
delegate.endDocument();
if (delegate instanceof ContentHandlerFactory.ObjectSource) {
Object obj = ((ContentHandlerFactory.ObjectSource)delegate).getObject();
if (inForeignObject) {
this.foreignObject = (Document)obj;
} else {
handleExternallyGeneratedObject(obj);
}
}
delegate = null; //Sub-document is processed, return to normal processing
}
} else {
if (NAMESPACE.equals(uri)) {
ElementHandler elementHandler = elementHandlers.get(localName);
if (elementHandler != null) {
try {
elementHandler.endElement();
} catch (IFException ife) {
handleIFException(ife);
}
content.setLength(0);
}
ignoreCharacters = true;
} else {
if (log.isTraceEnabled()) {
log.trace("Ignoring " + localName + " in namespace: " + uri);
}
}
}
}
// ============== Element handlers for the intermediate format =============
private interface ElementHandler {
void startElement(Attributes attributes) throws IFException, SAXException;
void endElement() throws IFException;
boolean ignoreCharacters();
}
private abstract class AbstractElementHandler implements ElementHandler {
public void startElement(Attributes attributes) throws IFException, SAXException {
//nop
}
public void endElement() throws IFException {
//nop
}
public boolean ignoreCharacters() {
return true;
}
}
private class DocumentHandler extends AbstractElementHandler {
public void startElement(Attributes attributes) throws IFException {
documentHandler.startDocument();
}
public void endElement() throws IFException {
documentHandler.endDocument();
}
}
private class DocumentHeaderHandler extends AbstractElementHandler {
public void startElement(Attributes attributes) throws IFException {
documentHandler.startDocumentHeader();
}
public void endElement() throws IFException {
documentHandler.endDocumentHeader();
}
}
private class LocaleHandler extends AbstractElementHandler {
public void startElement(Attributes attributes) throws IFException {
documentHandler.setDocumentLocale(getLanguage(attributes));
}
}
private class DocumentTrailerHandler extends AbstractElementHandler {
public void startElement(Attributes attributes) throws IFException {
documentHandler.startDocumentTrailer();
}
public void endElement() throws IFException {
documentHandler.endDocumentTrailer();
}
}
private class PageSequenceHandler extends AbstractElementHandler {
public void startElement(Attributes attributes) throws IFException {
String id = attributes.getValue("id");
Locale language = getLanguage(attributes);
if (language != null) {
documentHandler.getContext().setLanguage(language);
}
Map foreignAttributes = getForeignAttributes(lastAttributes);
establishForeignAttributes(foreignAttributes);
documentHandler.startPageSequence(id);
resetForeignAttributes();
}
public void endElement() throws IFException {
documentHandler.endPageSequence();
documentHandler.getContext().setLanguage(null);
}
}
private class PageHandler extends AbstractElementHandler {
public void startElement(Attributes attributes) throws IFException {
int index = Integer.parseInt(attributes.getValue("index"));
String name = attributes.getValue("name");
String pageMasterName = attributes.getValue("page-master-name");
int width = Integer.parseInt(attributes.getValue("width"));
int height = Integer.parseInt(attributes.getValue("height"));
Map foreignAttributes = getForeignAttributes(lastAttributes);
establishForeignAttributes(foreignAttributes);
documentHandler.startPage(index, name, pageMasterName,
new Dimension(width, height));
documentHandler.getContext().setPageNumber(index + 1);
resetForeignAttributes();
}
public void endElement() throws IFException {
documentHandler.endPage();
}
}
private class PageHeaderHandler extends AbstractElementHandler {
public void startElement(Attributes attributes) throws IFException {
documentHandler.startPageHeader();
structureTreeHandler = new StructureTreeHandler(userAgent.getStructureTreeEventHandler());
}
public void endElement() throws IFException {
documentHandler.endPageHeader();
}
}
private class PageContentHandler extends AbstractElementHandler {
public void startElement(Attributes attributes) throws IFException {
painter = documentHandler.startPageContent();
}
public void endElement() throws IFException {
painter = null;
documentHandler.getContext().setID("");
documentHandler.endPageContent();
}
}
private class PageTrailerHandler extends AbstractElementHandler {
public void startElement(Attributes attributes) throws IFException {
documentHandler.startPageTrailer();
}
public void endElement() throws IFException {
documentHandler.endPageTrailer();
}
}
private class ViewportHandler extends AbstractElementHandler {
public void startElement(Attributes attributes) throws IFException {
String transform = attributes.getValue("transform");
AffineTransform[] transforms
= AffineTransformArrayParser.createAffineTransform(transform);
int width = Integer.parseInt(attributes.getValue("width"));
int height = Integer.parseInt(attributes.getValue("height"));
Rectangle clipRect = XMLUtil.getAttributeAsRectangle(attributes, "clip-rect");
painter.startViewport(transforms, new Dimension(width, height), clipRect);
documentHandler.getContext().setRegionType(attributes.getValue("region-type"));
}
public void endElement() throws IFException {
painter.endViewport();
}
}
private class GroupHandler extends AbstractElementHandler {
public void startElement(Attributes attributes) throws IFException {
String transform = attributes.getValue("transform");
AffineTransform[] transforms
= AffineTransformArrayParser.createAffineTransform(transform);
String layer = attributes.getValue("layer");
painter.startGroup(transforms, layer);
}
public void endElement() throws IFException {
painter.endGroup();
}
}
private class IDHandler extends AbstractElementHandler {
@Override
public void startElement(Attributes attributes) throws IFException, SAXException {
String id = attributes.getValue("name");
documentHandler.getContext().setID(id);
}
}
private class FontHandler extends AbstractElementHandler {
public void startElement(Attributes attributes) throws IFException {
String family = attributes.getValue("family");
String style = attributes.getValue("style");
Integer weight = XMLUtil.getAttributeAsInteger(attributes, "weight");
String variant = attributes.getValue("variant");
Integer size = XMLUtil.getAttributeAsInteger(attributes, "size");
Color color;
try {
color = getAttributeAsColor(attributes, "color");
} catch (PropertyException pe) {
throw new IFException("Error parsing the color attribute", pe);
}
painter.setFont(family, style, weight, variant, size, color);
}
}
private class TextHandler extends AbstractElementHandler {
public void endElement() throws IFException {
int x = Integer.parseInt(lastAttributes.getValue("x"));
int y = Integer.parseInt(lastAttributes.getValue("y"));
String s = lastAttributes.getValue("letter-spacing");
int letterSpacing = (s != null ? Integer.parseInt(s) : 0);
s = lastAttributes.getValue("word-spacing");
int wordSpacing = (s != null ? Integer.parseInt(s) : 0);
int[] dx = XMLUtil.getAttributeAsIntArray(lastAttributes, "dx");
int[][] dp = XMLUtil.getAttributeAsPositionAdjustments(lastAttributes, "dp");
// if only DX present, then convert DX to DP; otherwise use only DP,
// effectively ignoring DX
if ((dp == null) && (dx != null)) {
dp = IFUtil.convertDXToDP(dx);
}
establishStructureTreeElement(lastAttributes);
boolean isHyphenated = Boolean.valueOf(lastAttributes.getValue("hyphenated"));
if (isHyphenated) {
documentHandler.getContext().setHyphenated(isHyphenated);
}
boolean nextIsSpace = Boolean.valueOf(lastAttributes.getValue("next-is-space"));
painter.drawText(x, y, letterSpacing, wordSpacing, dp, content.toString(), nextIsSpace);
documentHandler.getContext().setHyphenated(false);
resetStructureTreeElement();
}
public boolean ignoreCharacters() {
return false;
}
}
private class ClipRectHandler extends AbstractElementHandler {
public void startElement(Attributes attributes) throws IFException {
int x = Integer.parseInt(attributes.getValue("x"));
int y = Integer.parseInt(attributes.getValue("y"));
int width = Integer.parseInt(attributes.getValue("width"));
int height = Integer.parseInt(attributes.getValue("height"));
BorderProps[] borders = new BorderProps[4];
for (int i = 0; i < 4; i++) {
String b = attributes.getValue(SIDES[i]);
if (b != null) {
borders[i] = BorderProps.valueOf(userAgent, b);
}
}
if (!(borders[0] == null && borders[1] == null
&& borders[2] == null && borders[3] == null)) {
painter.clipBackground(new Rectangle(x, y, width, height),
borders[0], borders[1], borders[2], borders[3]);
}
painter.clipRect(new Rectangle(x, y, width, height));
}
}
private class RectHandler extends AbstractElementHandler {
public void startElement(Attributes attributes) throws IFException {
int x = Integer.parseInt(attributes.getValue("x"));
int y = Integer.parseInt(attributes.getValue("y"));
int width = Integer.parseInt(attributes.getValue("width"));
int height = Integer.parseInt(attributes.getValue("height"));
Color fillColor;
try {
fillColor = getAttributeAsColor(attributes, "fill");
} catch (PropertyException pe) {
throw new IFException("Error parsing the fill attribute", pe);
}
Rectangle rectangularArea = new Rectangle(x, y, width, height);
//TODO should rect be overloaded to include rounded corners
// or should we introduce a new IF element?
BorderProps[] borders = new BorderProps[4];
for (int i = 0; i < 4; i++) {
String b = attributes.getValue(SIDES[i]);
if (b != null) {
borders[i] = BorderProps.valueOf(userAgent, b);
}
}
if (!(borders[0] == null && borders[1] == null
&& borders[2] == null && borders[3] == null)) {
painter.clipBackground(rectangularArea,
borders[0], borders[1], borders[2], borders[3]);
}
painter.fillRect(rectangularArea , fillColor);
}
}
private class LineHandler extends AbstractElementHandler {
public void startElement(Attributes attributes) throws IFException {
int x1 = Integer.parseInt(attributes.getValue("x1"));
int y1 = Integer.parseInt(attributes.getValue("y1"));
int x2 = Integer.parseInt(attributes.getValue("x2"));
int y2 = Integer.parseInt(attributes.getValue("y2"));
int width = Integer.parseInt(attributes.getValue("stroke-width"));
Color color;
try {
color = getAttributeAsColor(attributes, "color");
} catch (PropertyException pe) {
throw new IFException("Error parsing the fill attribute", pe);
}
RuleStyle style = RuleStyle.valueOf(attributes.getValue("style"));
painter.drawLine(new Point(x1, y1), new Point(x2, y2), width, color, style);
}
}
private static final String[] SIDES = new String[] {"top", "bottom", "left", "right"};
private class BorderRectHandler extends AbstractElementHandler {
public void startElement(Attributes attributes) throws IFException {
int x = Integer.parseInt(attributes.getValue("x"));
int y = Integer.parseInt(attributes.getValue("y"));
int width = Integer.parseInt(attributes.getValue("width"));
int height = Integer.parseInt(attributes.getValue("height"));
BorderProps[] borders = new BorderProps[4];
for (int i = 0; i < 4; i++) {
String b = attributes.getValue(SIDES[i]);
if (b != null) {
borders[i] = BorderProps.valueOf(userAgent, b);
}
}
Color backgroundColor;
try {
backgroundColor = getAttributeAsColor(attributes, "inner-background-color");
} catch (PropertyException pe) {
throw new IFException("Error parsing the color attribute", pe);
}
painter.drawBorderRect(new Rectangle(x, y, width, height),
borders[0], borders[1], borders[2], borders[3], backgroundColor);
}
}
private class ImageHandler extends AbstractElementHandler {
public void startElement(Attributes attributes) throws IFException {
inForeignObject = true;
}
public void endElement() throws IFException {
int x = Integer.parseInt(lastAttributes.getValue("x"));
int y = Integer.parseInt(lastAttributes.getValue("y"));
int width = Integer.parseInt(lastAttributes.getValue("width"));
int height = Integer.parseInt(lastAttributes.getValue("height"));
Map foreignAttributes = getForeignAttributes(lastAttributes);
establishForeignAttributes(foreignAttributes);
establishStructureTreeElement(lastAttributes);
if (foreignObject != null) {
painter.drawImage(foreignObject,
new Rectangle(x, y, width, height));
foreignObject = null;
} else {
String uri = lastAttributes.getValue(
XLINK_HREF.getNamespaceURI(), XLINK_HREF.getLocalName());
if (uri == null) {
throw new IFException("xlink:href is missing on image", null);
}
painter.drawImage(uri, new Rectangle(x, y, width, height));
}
resetStructureTreeElement();
resetForeignAttributes();
inForeignObject = false;
}
public boolean ignoreCharacters() {
return false;
}
}
// ====================================================================
/**
* Handles objects created by "sub-parsers" that implement the ObjectSource interface.
* An example of object handled here are ExtensionAttachments.
* @param obj the Object to be handled.
* @throws SAXException if an error occurs while handling the extension object
*/
protected void handleExternallyGeneratedObject(Object obj) throws SAXException {
try {
documentHandler.handleExtensionObject(obj);
} catch (IFException ife) {
handleIFException(ife);
}
}
private Color getAttributeAsColor(Attributes attributes, String name)
throws PropertyException {
String s = attributes.getValue(name);
if (s == null) {
return null;
} else {
return ColorUtil.parseColorString(userAgent, s);
}
}
private static Map getForeignAttributes(Attributes atts) {
Map foreignAttributes = null;
for (int i = 0, c = atts.getLength(); i < c; i++) {
String ns = atts.getURI(i);
if (ns.length() > 0) {
if (handledNamespaces.contains(ns)) {
continue;
}
if (foreignAttributes == null) {
foreignAttributes = new java.util.HashMap();
}
QName qname = new QName(ns, atts.getQName(i));
foreignAttributes.put(qname, atts.getValue(i));
}
}
return foreignAttributes;
}
private void establishStructureTreeElement(Attributes attributes) {
StructureTreeElement element = getStructureTreeElement(attributes);
if (element != null) {
documentHandler.getContext().setStructureTreeElement(element);
}
}
private StructureTreeElement getStructureTreeElement(Attributes attributes) {
String structRef = attributes.getValue(InternalElementMapping.URI, InternalElementMapping.STRUCT_REF);
if (structRef != null && structRef.length() > 0) {
assert structureTreeElements.containsKey(structRef);
return structureTreeElements.get(structRef);
} else {
return null;
}
}
private void resetStructureTreeElement() {
documentHandler.getContext().resetStructureTreeElement();
}
/** {@inheritDoc} */
public void characters(char[] ch, int start, int length) throws SAXException {
if (delegate != null) {
delegate.characters(ch, start, length);
} else if (!ignoreCharacters) {
this.content.append(ch, start, length);
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy