| /* |
| * 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.layoutmgr; |
| |
| import java.awt.Dimension; |
| import java.awt.Rectangle; |
| import java.io.FileNotFoundException; |
| import java.io.IOException; |
| import java.net.URI; |
| import java.net.URISyntaxException; |
| |
| import org.apache.commons.logging.Log; |
| import org.apache.commons.logging.LogFactory; |
| |
| import org.apache.xmlgraphics.image.loader.ImageException; |
| import org.apache.xmlgraphics.image.loader.ImageInfo; |
| import org.apache.xmlgraphics.image.loader.ImageManager; |
| import org.apache.xmlgraphics.image.loader.util.ImageUtil; |
| |
| import org.apache.fop.ResourceEventProducer; |
| import org.apache.fop.apps.FOUserAgent; |
| import org.apache.fop.area.AreaTreeHandler; |
| import org.apache.fop.area.Block; |
| import org.apache.fop.area.BodyRegion; |
| import org.apache.fop.area.CTM; |
| import org.apache.fop.area.LineArea; |
| import org.apache.fop.area.PageSequence; |
| import org.apache.fop.area.PageViewport; |
| import org.apache.fop.area.RegionViewport; |
| import org.apache.fop.area.inline.Image; |
| import org.apache.fop.area.inline.InlineViewport; |
| import org.apache.fop.datatypes.FODimension; |
| import org.apache.fop.datatypes.URISpecification; |
| import org.apache.fop.fo.Constants; |
| import org.apache.fop.fo.extensions.ExternalDocument; |
| import org.apache.fop.layoutmgr.inline.ImageLayout; |
| import org.apache.fop.traits.WritingMode; |
| |
| /** |
| * LayoutManager for an external-document extension element. This class is instantiated by |
| * area.AreaTreeHandler for each fo:external-document found in the |
| * input document. |
| */ |
| public class ExternalDocumentLayoutManager extends AbstractPageSequenceLayoutManager { |
| |
| private static Log log = LogFactory.getLog(ExternalDocumentLayoutManager.class); |
| |
| private ImageLayout imageLayout; |
| |
| /** |
| * Constructor |
| * |
| * @param ath the area tree handler object |
| * @param document fox:external-document to process |
| */ |
| public ExternalDocumentLayoutManager(AreaTreeHandler ath, ExternalDocument document) { |
| super(ath, document); |
| } |
| |
| /** |
| * @return the ExternalDocument being managed by this layout manager |
| */ |
| protected ExternalDocument getExternalDocument() { |
| return (ExternalDocument)pageSeq; |
| } |
| |
| /** {@inheritDoc} */ |
| public PageSequenceLayoutManager getPSLM() { |
| throw new IllegalStateException("getPSLM() is illegal for " + getClass().getName()); |
| } |
| |
| /** {@inheritDoc} */ |
| public void activateLayout() { |
| initialize(); |
| |
| FOUserAgent userAgent = pageSeq.getUserAgent(); |
| ImageManager imageManager = userAgent.getImageManager(); |
| |
| String uri = URISpecification.getURL(getExternalDocument().getSrc()); |
| Integer firstPageIndex = ImageUtil.getPageIndexFromURI(uri); |
| boolean hasPageIndex = (firstPageIndex != null); |
| |
| try { |
| ImageInfo info = imageManager.getImageInfo(uri, userAgent.getImageSessionContext()); |
| |
| Object moreImages = info.getCustomObjects().get(ImageInfo.HAS_MORE_IMAGES); |
| boolean hasMoreImages = moreImages != null && !Boolean.FALSE.equals(moreImages); |
| |
| Dimension intrinsicSize = info.getSize().getDimensionMpt(); |
| ImageLayout layout = new ImageLayout(getExternalDocument(), this, intrinsicSize); |
| |
| PageSequence pageSequence = new PageSequence(null); |
| transferExtensions(pageSequence); |
| areaTreeHandler.getAreaTreeModel().startPageSequence(pageSequence); |
| if (log.isDebugEnabled()) { |
| log.debug("Starting layout"); |
| } |
| |
| makePageForImage(info, layout); |
| |
| if (!hasPageIndex && hasMoreImages) { |
| if (log.isTraceEnabled()) { |
| log.trace("Starting multi-page processing..."); |
| } |
| URI originalURI; |
| try { |
| originalURI = new URI(URISpecification.escapeURI(uri)); |
| int pageIndex = 1; |
| while (hasMoreImages) { |
| URI tempURI = new URI(originalURI.getScheme(), |
| originalURI.getSchemeSpecificPart(), |
| "page=" + Integer.toString(pageIndex + 1)); |
| if (log.isTraceEnabled()) { |
| log.trace("Subimage: " + tempURI.toASCIIString()); |
| } |
| ImageInfo subinfo = imageManager.getImageInfo( |
| tempURI.toASCIIString(), userAgent.getImageSessionContext()); |
| |
| moreImages = subinfo.getCustomObjects().get(ImageInfo.HAS_MORE_IMAGES); |
| hasMoreImages = moreImages != null && !Boolean.FALSE.equals(moreImages); |
| |
| intrinsicSize = subinfo.getSize().getDimensionMpt(); |
| layout = new ImageLayout( |
| getExternalDocument(), this, intrinsicSize); |
| |
| makePageForImage(subinfo, layout); |
| |
| pageIndex++; |
| } |
| } catch (URISyntaxException e) { |
| getResourceEventProducer().uriError(this, uri, e, |
| getExternalDocument().getLocator()); |
| } |
| } |
| } catch (FileNotFoundException fnfe) { |
| getResourceEventProducer().imageNotFound(this, uri, fnfe, |
| getExternalDocument().getLocator()); |
| } catch (IOException ioe) { |
| getResourceEventProducer().imageIOError(this, uri, ioe, |
| getExternalDocument().getLocator()); |
| } catch (ImageException ie) { |
| getResourceEventProducer().imageError(this, uri, ie, |
| getExternalDocument().getLocator()); |
| } |
| } |
| |
| private ResourceEventProducer getResourceEventProducer() { |
| return ResourceEventProducer.Provider.get( |
| getExternalDocument().getUserAgent().getEventBroadcaster()); |
| } |
| |
| private void makePageForImage(ImageInfo info, ImageLayout layout) { |
| this.imageLayout = layout; |
| curPage = makeNewPage(false); |
| fillPage(info.getOriginalURI()); |
| finishPage(); |
| } |
| |
| private void fillPage(String uri) { |
| |
| Dimension imageSize = this.imageLayout.getViewportSize(); |
| |
| Block blockArea = new Block(); |
| blockArea.setIPD(imageSize.width); |
| LineArea lineArea = new LineArea(); |
| |
| Image imageArea = new Image(uri); |
| TraitSetter.setProducerID(imageArea, fobj.getId()); |
| transferForeignAttributes(imageArea); |
| |
| InlineViewport vp = new InlineViewport(imageArea, fobj.getBidiLevel()); |
| TraitSetter.setProducerID(vp, fobj.getId()); |
| vp.setIPD(imageSize.width); |
| vp.setBPD(imageSize.height); |
| vp.setContentPosition(imageLayout.getPlacement()); |
| vp.setBlockProgressionOffset(0); |
| |
| //Link them all together... |
| lineArea.addInlineArea(vp); |
| lineArea.updateExtentsFromChildren(); |
| blockArea.addLineArea(lineArea); |
| curPage.getPageViewport().getCurrentFlow().addBlock(blockArea); |
| curPage.getPageViewport().getCurrentSpan().notifyFlowsFinished(); |
| } |
| |
| /** {@inheritDoc} */ |
| public void finishPageSequence() { |
| if (pageSeq.hasId()) { |
| idTracker.signalIDProcessed(pageSeq.getId()); |
| } |
| |
| pageSeq.getRoot().notifyPageSequenceFinished(currentPageNum, |
| (currentPageNum - startPageNum) + 1); |
| areaTreeHandler.notifyPageSequenceFinished(pageSeq, |
| (currentPageNum - startPageNum) + 1); |
| |
| if (log.isDebugEnabled()) { |
| log.debug("Ending layout"); |
| } |
| } |
| |
| /** {@inheritDoc} */ |
| protected Page createPage(int pageNumber, boolean isBlank) { |
| String pageNumberString = pageSeq.makeFormattedPageNumber(pageNumber); |
| |
| Dimension imageSize = this.imageLayout.getViewportSize(); |
| |
| // Set up the CTM on the page reference area based on writing-mode |
| // and reference-orientation |
| Rectangle referenceRect; |
| if (pageSeq.getReferenceOrientation() % 180 == 0) { |
| referenceRect = new Rectangle(0, 0, imageSize.width, imageSize.height); |
| } else { |
| referenceRect = new Rectangle(0, 0, imageSize.height, imageSize.width); |
| } |
| FODimension reldims = new FODimension(0, 0); |
| // [TBD] BIDI ALERT |
| CTM pageCTM = CTM.getCTMandRelDims(pageSeq.getReferenceOrientation(), |
| WritingMode.LR_TB, referenceRect, reldims); |
| |
| Page page = new Page(referenceRect, pageNumber, pageNumberString, isBlank); |
| |
| PageViewport pv = page.getPageViewport(); |
| org.apache.fop.area.Page pageArea = new org.apache.fop.area.Page(); |
| pv.setPage(pageArea); |
| |
| RegionViewport rv = new RegionViewport(referenceRect); |
| |
| if (pageSeq.getReferenceOrientation() % 180 == 0) { |
| rv.setIPD(referenceRect.width); |
| rv.setBPD(referenceRect.height); |
| } else { |
| rv.setIPD(referenceRect.height); |
| rv.setBPD(referenceRect.width); |
| } |
| rv.setClip(true); |
| |
| BodyRegion body = new BodyRegion(Constants.FO_REGION_BODY, |
| "fop-image-region", rv, 1, 0); |
| body.setIPD(imageSize.width); |
| body.setBPD(imageSize.height); |
| body.setCTM(pageCTM); |
| rv.setRegionReference(body); |
| pageArea.setRegionViewport( |
| Constants.FO_REGION_BODY, rv); |
| //Set unique key obtained from the AreaTreeHandler |
| pv.setKey(areaTreeHandler.generatePageViewportKey()); |
| |
| //Also creates first normal flow region |
| pv.createSpan(false); |
| |
| return page; |
| } |
| |
| } |