| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| /* $Id$ */ |
| |
| package org.apache.fop.render.xml; |
| |
| // Java |
| import java.awt.Color; |
| import java.awt.geom.Rectangle2D; |
| import java.io.IOException; |
| import java.io.OutputStream; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Map; |
| |
| import javax.xml.transform.TransformerConfigurationException; |
| import javax.xml.transform.sax.SAXTransformerFactory; |
| import javax.xml.transform.sax.TransformerHandler; |
| import javax.xml.transform.stream.StreamResult; |
| |
| import org.w3c.dom.Document; |
| import org.w3c.dom.Node; |
| import org.w3c.dom.NodeList; |
| import org.xml.sax.SAXException; |
| |
| import org.apache.xmlgraphics.util.QName; |
| import org.apache.xmlgraphics.util.XMLizable; |
| |
| import org.apache.fop.apps.FOPException; |
| import org.apache.fop.apps.FOUserAgent; |
| import org.apache.fop.apps.MimeConstants; |
| import org.apache.fop.area.Area; |
| import org.apache.fop.area.AreaTreeObject; |
| import org.apache.fop.area.BeforeFloat; |
| import org.apache.fop.area.Block; |
| import org.apache.fop.area.BlockViewport; |
| import org.apache.fop.area.BodyRegion; |
| import org.apache.fop.area.BookmarkData; |
| import org.apache.fop.area.CTM; |
| import org.apache.fop.area.DestinationData; |
| import org.apache.fop.area.Footnote; |
| import org.apache.fop.area.LineArea; |
| import org.apache.fop.area.MainReference; |
| import org.apache.fop.area.NormalFlow; |
| import org.apache.fop.area.OffDocumentExtensionAttachment; |
| import org.apache.fop.area.OffDocumentItem; |
| import org.apache.fop.area.PageSequence; |
| import org.apache.fop.area.PageViewport; |
| 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.Trait.InternalLink; |
| import org.apache.fop.area.inline.Container; |
| import org.apache.fop.area.inline.ForeignObject; |
| import org.apache.fop.area.inline.Image; |
| import org.apache.fop.area.inline.InlineArea; |
| import org.apache.fop.area.inline.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.extensions.ExtensionAttachment; |
| import org.apache.fop.fonts.FontInfo; |
| import org.apache.fop.fonts.FontTriplet; |
| import org.apache.fop.render.Renderer; |
| import org.apache.fop.render.RendererContext; |
| import org.apache.fop.render.XMLHandler; |
| import org.apache.fop.util.ColorUtil; |
| import org.apache.fop.util.DOM2SAX; |
| |
| /** |
| * Renderer that renders areas to XML for debugging purposes. |
| * This creates an xml that contains the information of the area |
| * tree. It does not output any state or derived information. |
| * The output can be used to build a new area tree which can be |
| * rendered to any renderer. |
| */ |
| public class XMLRenderer extends AbstractXMLRenderer { |
| |
| /** XML MIME type */ |
| public static final String XML_MIME_TYPE = MimeConstants.MIME_FOP_AREA_TREE; |
| |
| private boolean startedSequence = false; |
| private boolean compactFormat = false; |
| |
| /** If not null, the XMLRenderer will mimic another renderer by using its font setup. */ |
| protected Renderer mimic; |
| |
| private int pageSequenceIndex; |
| |
| /** |
| * Creates a new XML renderer. |
| */ |
| public XMLRenderer() { |
| context = new RendererContext(this, XML_MIME_TYPE); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public void setUserAgent(FOUserAgent agent) { |
| super.setUserAgent(agent); |
| |
| XMLHandler xmlHandler = new XMLXMLHandler(); |
| userAgent.getXMLHandlerRegistry().addXMLHandler(xmlHandler); |
| Boolean b = (Boolean)userAgent.getRendererOptions().get("compact-format"); |
| if (b != null) { |
| setCompactFormat(b.booleanValue()); |
| } |
| } |
| |
| /** |
| * 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; |
| } |
| |
| /** {@inheritDoc} */ |
| public void setupFontInfo(FontInfo inFontInfo) throws FOPException { |
| if (mimic != null) { |
| mimic.setupFontInfo(inFontInfo); |
| } else { |
| super.setupFontInfo(inFontInfo); |
| } |
| } |
| |
| public void setCompactFormat(boolean compact) { |
| this.compactFormat = compact; |
| } |
| |
| private boolean isDetailedFormat() { |
| return !this.compactFormat; |
| } |
| |
| /** |
| * Adds the general Area attributes. |
| * @param area Area to extract attributes from |
| */ |
| protected void addAreaAttributes(Area area) { |
| addAttribute("ipd", area.getIPD()); |
| addAttribute("bpd", area.getBPD()); |
| if (isDetailedFormat()) { |
| if (area.getIPD() != 0) { |
| addAttribute("ipda", area.getAllocIPD()); |
| } |
| if (area.getBPD() != 0) { |
| addAttribute("bpda", area.getAllocBPD()); |
| } |
| addAttribute("bap", area.getBorderAndPaddingWidthStart() + " " |
| + area.getBorderAndPaddingWidthEnd() + " " |
| + area.getBorderAndPaddingWidthBefore() + " " |
| + area.getBorderAndPaddingWidthAfter()); |
| } |
| } |
| |
| /** |
| * Adds attributes from traits of an Area. |
| * @param area Area to extract traits from |
| */ |
| protected void addTraitAttributes(Area area) { |
| Map traitMap = area.getTraits(); |
| if (traitMap != null) { |
| Iterator iter = traitMap.entrySet().iterator(); |
| while (iter.hasNext()) { |
| Map.Entry traitEntry = (Map.Entry) iter.next(); |
| Object key = traitEntry.getKey(); |
| String name = Trait.getTraitName(key); |
| Class clazz = Trait.getTraitClass(key); |
| if ("break-before".equals(name) || "break-after".equals(name)) { |
| continue; |
| } |
| Object value = traitEntry.getValue(); |
| if (key == Trait.FONT) { |
| FontTriplet triplet = (FontTriplet)value; |
| addAttribute("font-name", triplet.getName()); |
| addAttribute("font-style", triplet.getStyle()); |
| addAttribute("font-weight", triplet.getWeight()); |
| } else if (clazz.equals(InternalLink.class)) { |
| InternalLink iLink = (InternalLink)value; |
| addAttribute(name, iLink.xmlAttribute()); |
| } 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 if (clazz.equals(Color.class)) { |
| Color c = (Color)value; |
| addAttribute(name, ColorUtil.colorToString(c)); |
| } else if (key == Trait.START_INDENT || key == Trait.END_INDENT) { |
| if (((Integer)value).intValue() != 0) { |
| addAttribute(name, value.toString()); |
| } |
| } else { |
| addAttribute(name, value.toString()); |
| } |
| } |
| } |
| |
| transferForeignObjects(area); |
| } |
| |
| private void transferForeignObjects(AreaTreeObject ato) { |
| Map prefixes = new java.util.HashMap(); |
| Iterator iter = ato.getForeignAttributes().entrySet().iterator(); |
| while (iter.hasNext()) { |
| Map.Entry entry = (Map.Entry)iter.next(); |
| QName qname = (QName)entry.getKey(); |
| prefixes.put(qname.getPrefix(), qname.getNamespaceURI()); |
| addAttribute(qname, (String)entry.getValue()); |
| } |
| //Namespace declarations |
| iter = prefixes.entrySet().iterator(); |
| while (iter.hasNext()) { |
| Map.Entry entry = (Map.Entry)iter.next(); |
| String qn = "xmlns:" + (String)entry.getKey(); |
| atts.addAttribute("", (String)entry.getKey(), qn, |
| CDATA, (String)entry.getValue()); |
| } |
| } |
| |
| /** {@inheritDoc} */ |
| public void processOffDocumentItem(OffDocumentItem oDI) { |
| if (oDI instanceof BookmarkData) { |
| renderBookmarkTree((BookmarkData) oDI); |
| } else if (oDI instanceof DestinationData) { |
| renderDestination((DestinationData) oDI); |
| } else if (oDI instanceof OffDocumentExtensionAttachment) { |
| ExtensionAttachment attachment = ((OffDocumentExtensionAttachment)oDI).getAttachment(); |
| if (extensionAttachments == null) { |
| extensionAttachments = new java.util.ArrayList(); |
| } |
| extensionAttachments.add(attachment); |
| } else { |
| String warn = "Ignoring OffDocumentItem: " + oDI; |
| log.warn(warn); |
| } |
| } |
| |
| /** |
| * Renders a BookmarkTree object |
| * @param bookmarkRoot the BookmarkData object representing the top of the tree |
| */ |
| protected void renderBookmarkTree(BookmarkData bookmarkRoot) { |
| if (bookmarkRoot.getWhenToProcess() == OffDocumentItem.END_OF_DOC) { |
| endPageSequence(); |
| } |
| /* If this kind of handling is also necessary for other renderers, then |
| better add endPageSequence to the Renderer interface and call it |
| explicitly from model.endDocument() */ |
| |
| startElement("bookmarkTree"); |
| for (int i = 0; i < bookmarkRoot.getCount(); i++) { |
| renderBookmarkItem(bookmarkRoot.getSubData(i)); |
| } |
| endElement("bookmarkTree"); |
| } |
| |
| private void renderBookmarkItem(BookmarkData bm) { |
| atts.clear(); |
| addAttribute("title", bm.getBookmarkTitle()); |
| addAttribute("show-children", String.valueOf(bm.showChildItems())); |
| PageViewport pv = bm.getPageViewport(); |
| String pvKey = pv == null ? null : pv.getKey(); |
| addAttribute("internal-link", |
| InternalLink.makeXMLAttribute(pvKey, bm.getIDRef())); |
| startElement("bookmark", atts); |
| for (int i = 0; i < bm.getCount(); i++) { |
| renderBookmarkItem(bm.getSubData(i)); |
| } |
| endElement("bookmark"); |
| } |
| |
| /** |
| * Renders a DestinationData object (named destination) |
| * @param destination the destination object |
| */ |
| protected void renderDestination(DestinationData destination) { |
| if (destination.getWhenToProcess() == OffDocumentItem.END_OF_DOC) { |
| endPageSequence(); |
| } |
| atts.clear(); |
| PageViewport pv = destination.getPageViewport(); |
| String pvKey = pv == null ? null : pv.getKey(); |
| addAttribute("internal-link", |
| InternalLink.makeXMLAttribute(pvKey, destination.getIDRef())); |
| startElement("destination", atts); |
| endElement("destination"); |
| } |
| |
| /** {@inheritDoc} */ |
| public void startRenderer(OutputStream outputStream) |
| throws IOException { |
| log.debug("Rendering areas to Area Tree XML"); |
| |
| if (this.handler == null) { |
| SAXTransformerFactory factory |
| = (SAXTransformerFactory)SAXTransformerFactory.newInstance(); |
| try { |
| TransformerHandler transformerHandler = factory.newTransformerHandler(); |
| this.handler = transformerHandler; |
| StreamResult res = new StreamResult(outputStream); |
| transformerHandler.setResult(res); |
| } catch (TransformerConfigurationException tce) { |
| throw new RuntimeException(tce.getMessage()); |
| } |
| |
| this.out = outputStream; |
| } |
| |
| try { |
| handler.startDocument(); |
| } catch (SAXException saxe) { |
| handleSAXException(saxe); |
| } |
| if (userAgent.getProducer() != null) { |
| comment("Produced by " + userAgent.getProducer()); |
| } |
| startElement("areaTree"); |
| } |
| |
| /** {@inheritDoc} */ |
| public void stopRenderer() throws IOException { |
| endPageSequence(); |
| endElement("areaTree"); |
| try { |
| handler.endDocument(); |
| } catch (SAXException saxe) { |
| handleSAXException(saxe); |
| } |
| if (this.out != null) { |
| this.out.flush(); |
| } |
| log.debug("Written out Area Tree XML"); |
| } |
| |
| /** {@inheritDoc} */ |
| public void renderPage(PageViewport page) throws IOException, FOPException { |
| atts.clear(); |
| addAttribute("bounds", page.getViewArea()); |
| addAttribute("key", page.getKey()); |
| addAttribute("nr", page.getPageNumber()); |
| addAttribute("formatted-nr", page.getPageNumberString()); |
| if (page.getSimplePageMasterName() != null) { |
| addAttribute("simple-page-master-name", page.getSimplePageMasterName()); |
| } |
| if (page.isBlank()) { |
| addAttribute("blank", "true"); |
| } |
| transferForeignObjects(page); |
| startElement("pageViewport", atts); |
| startElement("page"); |
| |
| handlePageExtensionAttachments(page); |
| super.renderPage(page); |
| |
| endElement("page"); |
| endElement("pageViewport"); |
| } |
| |
| /** {@inheritDoc} */ |
| protected void handleExtensionAttachments(List attachments) { |
| if (attachments != null && attachments.size() > 0) { |
| startElement("extension-attachments"); |
| Iterator i = attachments.iterator(); |
| while (i.hasNext()) { |
| ExtensionAttachment attachment = (ExtensionAttachment)i.next(); |
| if (attachment instanceof XMLizable) { |
| try { |
| ((XMLizable)attachment).toSAX(this.handler); |
| } catch (SAXException e) { |
| log.error("Error while serializing Extension Attachment", e); |
| } |
| } else { |
| String warn = "Ignoring non-XMLizable ExtensionAttachment: " + attachment; |
| log.warn(warn); |
| } |
| } |
| endElement("extension-attachments"); |
| } |
| } |
| |
| /** {@inheritDoc} */ |
| public void startPageSequence(PageSequence pageSequence) { |
| handleDocumentExtensionAttachments(); |
| endPageSequence(); // move this before handleDocumentExtensionAttachments() ? |
| startedSequence = true; |
| atts.clear(); |
| if (pageSequence.getLanguage() != null) { |
| addAttribute("language", pageSequence.getLanguage()); |
| } |
| if (pageSequence.getCountry() != null) { |
| addAttribute("country", pageSequence.getCountry()); |
| } |
| transferForeignObjects(pageSequence); |
| startElement("pageSequence", atts); |
| if (this.getUserAgent().isAccessibilityEnabled()) { |
| String structureTreeElement = "structureTree"; |
| startElement(structureTreeElement); |
| NodeList nodes = getUserAgent().getStructureTree().getPageSequence(pageSequenceIndex++); |
| for (int i = 0, n = nodes.getLength(); i < n; i++) { |
| Node node = nodes.item(i); |
| try { |
| new DOM2SAX(handler).writeFragment(node); |
| } catch (SAXException e) { |
| handleSAXException(e); |
| } |
| } |
| endElement(structureTreeElement); |
| } |
| handleExtensionAttachments(pageSequence.getExtensionAttachments()); |
| LineArea seqTitle = pageSequence.getTitle(); |
| if (seqTitle != null) { |
| startElement("title"); |
| List children = seqTitle.getInlineAreas(); |
| |
| for (int count = 0; count < children.size(); count++) { |
| InlineArea inline = (InlineArea) children.get(count); |
| renderInlineArea(inline); |
| } |
| |
| endElement("title"); |
| } |
| } |
| |
| /** |
| * Tells the renderer to finish the current PageSequence |
| */ |
| public void endPageSequence() { |
| if (startedSequence) { |
| endElement("pageSequence"); |
| } |
| startedSequence = false; |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| protected void renderRegionViewport(RegionViewport port) { |
| if (port != null) { |
| atts.clear(); |
| addAreaAttributes(port); |
| addTraitAttributes(port); |
| addAttribute("rect", port.getViewArea()); |
| if (port.isClip()) { |
| addAttribute("clipped", "true"); |
| } |
| startElement("regionViewport", atts); |
| RegionReference region = port.getRegionReference(); |
| atts.clear(); |
| addAreaAttributes(region); |
| addTraitAttributes(region); |
| addAttribute("name", region.getRegionName()); |
| addAttribute("ctm", region.getCTM().toString()); |
| if (region.getRegionClass() == FO_REGION_BEFORE) { |
| startElement("regionBefore", atts); |
| renderRegion(region); |
| endElement("regionBefore"); |
| } else if (region.getRegionClass() == FO_REGION_START) { |
| startElement("regionStart", atts); |
| 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(body); |
| endElement("regionBody"); |
| } else if (region.getRegionClass() == FO_REGION_END) { |
| startElement("regionEnd", atts); |
| renderRegion(region); |
| endElement("regionEnd"); |
| } else if (region.getRegionClass() == FO_REGION_AFTER) { |
| startElement("regionAfter", atts); |
| renderRegion(region); |
| endElement("regionAfter"); |
| } |
| endElement("regionViewport"); |
| } |
| } |
| |
| /** {@inheritDoc} */ |
| protected void startVParea(CTM ctm, Rectangle2D clippingRect) { |
| //only necessary for graphical output |
| } |
| |
| /** {@inheritDoc} */ |
| protected void endVParea() { |
| //only necessary for graphical output |
| } |
| |
| /** |
| * {@inheritDoc} |
| * org.apache.fop.area.inline.InlineArea) |
| */ |
| protected void renderInlineAreaBackAndBorders(InlineArea area) { |
| //only necessary for graphical output |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| protected void renderBeforeFloat(BeforeFloat bf) { |
| startElement("beforeFloat"); |
| super.renderBeforeFloat(bf); |
| endElement("beforeFloat"); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| protected void renderFootnote(Footnote footnote) { |
| atts.clear(); |
| addAttribute("top-offset", footnote.getTop()); |
| startElement("footnote", atts); |
| super.renderFootnote(footnote); |
| endElement("footnote"); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| protected void renderMainReference(MainReference mr) { |
| atts.clear(); |
| addAreaAttributes(mr); |
| addTraitAttributes(mr); |
| if (mr.getColumnCount() != 1) { |
| addAttribute("columnGap", mr.getColumnGap()); |
| } |
| startElement("mainReference", atts); |
| |
| Span span = null; |
| List spans = mr.getSpans(); |
| 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); |
| for (int c = 0; c < span.getColumnCount(); c++) { |
| NormalFlow flow = (NormalFlow) span.getNormalFlow(c); |
| |
| renderFlow(flow); |
| } |
| endElement("span"); |
| } |
| endElement("mainReference"); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| protected void renderFlow(NormalFlow flow) { |
| // the normal flow reference area contains stacked blocks |
| atts.clear(); |
| addAreaAttributes(flow); |
| addTraitAttributes(flow); |
| startElement("flow", atts); |
| super.renderFlow(flow); |
| endElement("flow"); |
| } |
| |
| /** {@inheritDoc} */ |
| protected void renderReferenceArea(Block block) { |
| handleBlockTraits(block); |
| |
| List children = block.getChildAreas(); |
| if (children != null) { |
| renderBlocks(block, children); |
| } |
| } |
| |
| /** {@inheritDoc} */ |
| protected void renderBlock(Block block) { |
| 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 |
| || bvp.getPositioning() == Block.FIXED) { |
| abspos = true; |
| } |
| if (abspos) { |
| addAttribute("left-position", bvp.getXOffset()); |
| addAttribute("top-position", bvp.getYOffset()); |
| } |
| addAttribute("ctm", bvp.getCTM().toString()); |
| if (bvp.getClip()) { |
| addAttribute("clipped", "true"); |
| } |
| } else { |
| if (block.getXOffset() != 0) { |
| addAttribute("left-offset", block.getXOffset()); |
| } |
| if (block.getYOffset() != 0) { |
| 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"); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| protected void renderLineArea(LineArea line) { |
| atts.clear(); |
| addAreaAttributes(line); |
| addTraitAttributes(line); |
| startElement("lineArea", atts); |
| super.renderLineArea(line); |
| endElement("lineArea"); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| protected void renderInlineArea(InlineArea inlineArea) { |
| atts.clear(); |
| if (inlineArea.getClass() == InlineArea.class) { |
| // Generic inline area. This is implemented to allow the 0x0 "dummy" |
| // area generated by fo:wrapper to pass its id. |
| addAreaAttributes(inlineArea); |
| addTraitAttributes(inlineArea); |
| startElement("inline", atts); |
| endElement("inline"); |
| } else { |
| super.renderInlineArea(inlineArea); |
| // calls specific renderers for Text, Space, Viewport, etc. etc. |
| } |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| protected void renderViewport(Viewport viewport) { |
| atts.clear(); |
| addAreaAttributes(viewport); |
| addTraitAttributes(viewport); |
| addAttribute("offset", viewport.getOffset()); |
| addAttribute("pos", viewport.getContentPosition()); |
| if (viewport.getClip()) { |
| addAttribute("clip", "true"); |
| } |
| startElement("viewport", atts); |
| super.renderViewport(viewport); |
| endElement("viewport"); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public void renderImage(Image image, Rectangle2D pos) { |
| atts.clear(); |
| addAreaAttributes(image); |
| addTraitAttributes(image); |
| addAttribute("url", image.getURL()); |
| //addAttribute("pos", pos); |
| startElement("image", atts); |
| endElement("image"); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public void renderContainer(Container cont) { |
| startElement("container"); |
| super.renderContainer(cont); |
| endElement("container"); |
| } |
| |
| /** |
| * Renders an fo:foreing-object. |
| * @param fo the foreign object |
| * @param pos the position of the foreign object |
| * @see org.apache.fop.render.AbstractRenderer#renderForeignObject(ForeignObject, Rectangle2D) |
| */ |
| public void renderForeignObject(ForeignObject fo, Rectangle2D pos) { |
| atts.clear(); |
| addAreaAttributes(fo); |
| addTraitAttributes(fo); |
| String ns = fo.getNameSpace(); |
| addAttribute("ns", ns); |
| startElement("foreignObject", atts); |
| Document doc = fo.getDocument(); |
| context.setProperty(XMLXMLHandler.HANDLER, handler); |
| renderXML(context, doc, ns); |
| endElement("foreignObject"); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| protected void renderInlineSpace(Space space) { |
| atts.clear(); |
| addAreaAttributes(space); |
| addTraitAttributes(space); |
| addAttribute("offset", space.getOffset()); |
| startElement("space", atts); |
| endElement("space"); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| protected void renderText(TextArea text) { |
| atts.clear(); |
| if (text.getTextWordSpaceAdjust() != 0) { |
| addAttribute("twsadjust", text.getTextWordSpaceAdjust()); |
| } |
| if (text.getTextLetterSpaceAdjust() != 0) { |
| addAttribute("tlsadjust", text.getTextLetterSpaceAdjust()); |
| } |
| addAttribute("offset", text.getOffset()); |
| addAttribute("baseline", text.getBaselineOffset()); |
| addAreaAttributes(text); |
| addTraitAttributes(text); |
| startElement("text", atts); |
| super.renderText(text); |
| endElement("text"); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| protected void renderWord(WordArea word) { |
| atts.clear(); |
| addAttribute("offset", word.getOffset()); |
| int[] letterAdjust = word.getLetterAdjustArray(); |
| if (letterAdjust != null) { |
| StringBuffer sb = new StringBuffer(64); |
| boolean nonZeroFound = false; |
| for (int i = 0, c = letterAdjust.length; i < c; i++) { |
| if (i > 0) { |
| sb.append(' '); |
| } |
| sb.append(letterAdjust[i]); |
| nonZeroFound |= (letterAdjust[i] != 0); |
| } |
| if (nonZeroFound) { |
| addAttribute("letter-adjust", sb.toString()); |
| } |
| } |
| startElement("word", atts); |
| characters(word.getWord()); |
| endElement("word"); |
| super.renderWord(word); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| protected void renderSpace(SpaceArea space) { |
| atts.clear(); |
| addAttribute("offset", space.getOffset()); |
| if (!space.isAdjustable()) { |
| addAttribute("adj", "false"); //default is true |
| } |
| startElement("space", atts); |
| characters(space.getSpace()); |
| endElement("space"); |
| super.renderSpace(space); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| protected void renderInlineParent(InlineParent ip) { |
| atts.clear(); |
| addAreaAttributes(ip); |
| addTraitAttributes(ip); |
| addAttribute("offset", ip.getOffset()); |
| startElement("inlineparent", atts); |
| super.renderInlineParent(ip); |
| endElement("inlineparent"); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| protected void renderInlineBlockParent(InlineBlockParent ibp) { |
| atts.clear(); |
| addAreaAttributes(ibp); |
| addTraitAttributes(ibp); |
| addAttribute("offset", ibp.getOffset()); |
| startElement("inlineblockparent", atts); |
| super.renderInlineBlockParent(ibp); |
| endElement("inlineblockparent"); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| protected void renderLeader(Leader area) { |
| atts.clear(); |
| addAreaAttributes(area); |
| addTraitAttributes(area); |
| addAttribute("offset", area.getOffset()); |
| addAttribute("ruleStyle", area.getRuleStyleAsString()); |
| addAttribute("ruleThickness", area.getRuleThickness()); |
| startElement("leader", atts); |
| endElement("leader"); |
| super.renderLeader(area); |
| } |
| |
| /** {@inheritDoc} */ |
| public String getMimeType() { |
| return XML_MIME_TYPE; |
| } |
| |
| } |
| |