From: Jeremias Maerki Date: Tue, 28 Dec 2004 18:03:12 +0000 (+0000) Subject: Support for percentages on external-graphic and instream-foreign-object for the conte... X-Git-Tag: Root_Temp_KnuthStylePageBreaking~292 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=73a83df9636693496269245c4f0b5fcd56aae0b1;p=xmlgraphics-fop.git Support for percentages on external-graphic and instream-foreign-object for the content-height and content-width attributes. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@198215 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/src/java/org/apache/fop/datatypes/LengthBase.java b/src/java/org/apache/fop/datatypes/LengthBase.java index 45df34d8c..c6e229b89 100644 --- a/src/java/org/apache/fop/datatypes/LengthBase.java +++ b/src/java/org/apache/fop/datatypes/LengthBase.java @@ -20,6 +20,7 @@ package org.apache.fop.datatypes; import org.apache.fop.fo.Constants; import org.apache.fop.fo.FObj; +import org.apache.fop.fo.IntrinsicSizeAccess; import org.apache.fop.fo.PropertyList; import org.apache.fop.fo.expr.PropertyException; @@ -43,11 +44,16 @@ public class LengthBase implements PercentBase { public static final int BLOCK_WIDTH = 5; /** constant for a containing block percent-based length */ public static final int BLOCK_HEIGHT = 6; + /** constant for a image intrinsic percent-based length */ + public static final int IMAGE_INTRINSIC_WIDTH = 7; + /** constant for a image intrinsic percent-based length */ + public static final int IMAGE_INTRINSIC_HEIGHT = 8; /** array of valid percent-based length types */ public static final int[] PERCENT_BASED_LENGTH_TYPES - = { CUSTOM_BASE, FONTSIZE, INH_FONTSIZE, CONTAINING_BOX, - CONTAINING_REFAREA } ; + = {CUSTOM_BASE, FONTSIZE, INH_FONTSIZE, CONTAINING_BOX, + CONTAINING_REFAREA, + IMAGE_INTRINSIC_WIDTH, IMAGE_INTRINSIC_HEIGHT}; /** * FO parent of the FO for which this property is to be calculated. @@ -122,13 +128,15 @@ public class LengthBase implements PercentBase { case BLOCK_HEIGHT: return parentFO.getLayoutDimension(PercentBase.BLOCK_BPD).intValue(); case CONTAINING_REFAREA: // example: start-indent, end-indent - { //FONode fo; //for (fo = parentFO; fo != null && !fo.generatesReferenceAreas(); // fo = fo.getParent()); //return (((fo != null) && (fo instanceof FObj)) ? ((FObj)fo).getContentWidth() : 0); return 0; - } + case IMAGE_INTRINSIC_WIDTH: + return ((IntrinsicSizeAccess)propertyList.getFObj()).getIntrinsicWidth(); + case IMAGE_INTRINSIC_HEIGHT: + return ((IntrinsicSizeAccess)propertyList.getFObj()).getIntrinsicHeight(); case CUSTOM_BASE: //log.debug("!!! LengthBase.getBaseLength() called on CUSTOM_BASE type !!!"); return 0; diff --git a/src/java/org/apache/fop/fo/FOPropertyMapping.java b/src/java/org/apache/fop/fo/FOPropertyMapping.java index 14878037f..127e2668d 100644 --- a/src/java/org/apache/fop/fo/FOPropertyMapping.java +++ b/src/java/org/apache/fop/fo/FOPropertyMapping.java @@ -1418,6 +1418,7 @@ public class FOPropertyMapping implements Constants { l.addEnum("auto", makeEnumProperty(EN_AUTO, "AUTO")); l.addEnum("scale-to-fit", makeEnumProperty(EN_SCALE_TO_FIT, "SCALE_TO_FIT")); l.setDefault("auto"); + l.setPercentBase(LengthBase.IMAGE_INTRINSIC_HEIGHT); addPropertyMaker("content-height", l); // content-width @@ -1426,6 +1427,7 @@ public class FOPropertyMapping implements Constants { l.addEnum("auto", makeEnumProperty(EN_AUTO, "AUTO")); l.addEnum("scale-to-fit", makeEnumProperty(EN_SCALE_TO_FIT, "SCALE_TO_FIT")); l.setDefault("auto"); + l.setPercentBase(LengthBase.IMAGE_INTRINSIC_WIDTH); addPropertyMaker("content-width", l); // height diff --git a/src/java/org/apache/fop/fo/IntrinsicSizeAccess.java b/src/java/org/apache/fop/fo/IntrinsicSizeAccess.java new file mode 100644 index 000000000..07e2e2afa --- /dev/null +++ b/src/java/org/apache/fop/fo/IntrinsicSizeAccess.java @@ -0,0 +1,37 @@ +/* + * Copyright 2004 The Apache Software Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* $Id$ */ + +package org.apache.fop.fo; + +/** + * This interface defines the interface for LengthBase to access the intrinsic + * size of an image (for external-graphic and instream-foreign-object). + */ +public interface IntrinsicSizeAccess { + + /** + * @return the intrinsic width of an image (in millipoints). + */ + int getIntrinsicWidth(); + + /** + * @return the intrinsic height of an image (in millipoints). + */ + int getIntrinsicHeight(); + +} diff --git a/src/java/org/apache/fop/fo/flow/ExternalGraphic.java b/src/java/org/apache/fop/fo/flow/ExternalGraphic.java index 55c5a567d..7d609028e 100644 --- a/src/java/org/apache/fop/fo/flow/ExternalGraphic.java +++ b/src/java/org/apache/fop/fo/flow/ExternalGraphic.java @@ -27,6 +27,7 @@ import org.apache.fop.apps.FOPException; import org.apache.fop.datatypes.Length; import org.apache.fop.fo.FONode; import org.apache.fop.fo.FObj; +import org.apache.fop.fo.IntrinsicSizeAccess; import org.apache.fop.fo.PropertyList; import org.apache.fop.fo.ValidationException; import org.apache.fop.fo.properties.CommonAccessibility; @@ -36,6 +37,8 @@ import org.apache.fop.fo.properties.CommonMarginInline; import org.apache.fop.fo.properties.CommonRelativePosition; import org.apache.fop.fo.properties.KeepProperty; import org.apache.fop.fo.properties.LengthRangeProperty; +import org.apache.fop.image.FopImage; +import org.apache.fop.image.ImageFactory; import org.apache.fop.layoutmgr.ExternalGraphicLayoutManager; /** @@ -43,7 +46,8 @@ import org.apache.fop.layoutmgr.ExternalGraphicLayoutManager; * This FO node handles the external graphic. It creates an image * inline area that can be added to the area tree. */ -public class ExternalGraphic extends FObj { +public class ExternalGraphic extends FObj implements IntrinsicSizeAccess { + // The value of properties relevant for fo:external-graphic. private CommonAccessibility commonAccessibility; private CommonAural commonAural; @@ -75,6 +79,10 @@ public class ExternalGraphic extends FObj { private Length width; // End of property values + //Additional values + private String url; + private FopImage fopimage; + /** * Create a new External graphic node. * @@ -116,6 +124,9 @@ public class ExternalGraphic extends FObj { textAlign = pList.get(PR_TEXT_ALIGN).getEnum(); verticalAlign = pList.get(PR_VERTICAL_ALIGN).getEnum(); width = pList.get(PR_WIDTH).getLength(); + + //Additional processing + url = ImageFactory.getURL(getSrc()); } /** @@ -219,6 +230,13 @@ public class ExternalGraphic extends FObj { return src; } + /** + * @return Get the resulting URL based on the src property. + */ + public String getURL() { + return url; + } + /** * Return the "text-align" property. */ @@ -253,4 +271,48 @@ public class ExternalGraphic extends FObj { public int getNameId() { return FO_EXTERNAL_GRAPHIC; } + + /** + * Preloads the image so the intrinsic size is available. + */ + private void prepareIntrinsicSize() { + if (fopimage == null) { + ImageFactory fact = ImageFactory.getInstance(); + fopimage = fact.getImage(getURL(), getUserAgent()); + if (fopimage == null) { + getLogger().error("Image not available: " + getURL()); + } else { + // load dimensions + if (!fopimage.load(FopImage.DIMENSIONS)) { + getLogger().error("Cannot read image dimensions: " + getURL()); + } + } + //TODO Report to caller so he can decide to throw an exception + } + } + + /** + * @see org.apache.fop.fo.IntrinsicSizeAccess#getIntrinsicWidth() + */ + public int getIntrinsicWidth() { + prepareIntrinsicSize(); + if (fopimage != null) { + return fopimage.getWidth() * 1000; + } else { + return 0; + } + } + + /** + * @see org.apache.fop.fo.IntrinsicSizeAccess#getIntrinsicHeight() + */ + public int getIntrinsicHeight() { + prepareIntrinsicSize(); + if (fopimage != null) { + return fopimage.getHeight() * 1000; + } else { + return 0; + } + } + } diff --git a/src/java/org/apache/fop/fo/flow/InstreamForeignObject.java b/src/java/org/apache/fop/fo/flow/InstreamForeignObject.java index 60c36f271..f8ffccbd0 100644 --- a/src/java/org/apache/fop/fo/flow/InstreamForeignObject.java +++ b/src/java/org/apache/fop/fo/flow/InstreamForeignObject.java @@ -18,8 +18,7 @@ package org.apache.fop.fo.flow; -// Java -import java.util.List; +import java.awt.geom.Point2D; import org.xml.sax.Locator; @@ -27,8 +26,10 @@ import org.apache.fop.apps.FOPException; import org.apache.fop.datatypes.Length; import org.apache.fop.fo.FONode; import org.apache.fop.fo.FObj; +import org.apache.fop.fo.IntrinsicSizeAccess; import org.apache.fop.fo.PropertyList; import org.apache.fop.fo.ValidationException; +import org.apache.fop.fo.XMLObj; import org.apache.fop.fo.properties.CommonAccessibility; import org.apache.fop.fo.properties.CommonAural; import org.apache.fop.fo.properties.CommonBorderPaddingBackground; @@ -36,14 +37,14 @@ import org.apache.fop.fo.properties.CommonMarginInline; import org.apache.fop.fo.properties.CommonRelativePosition; import org.apache.fop.fo.properties.KeepProperty; import org.apache.fop.fo.properties.LengthRangeProperty; -import org.apache.fop.layoutmgr.InstreamForeignObjectLM; /** * The instream-foreign-object flow formatting object. * This is an atomic inline object that contains * xml data. */ -public class InstreamForeignObject extends FObj { +public class InstreamForeignObject extends FObj implements IntrinsicSizeAccess { + // The value of properties relevant for fo:instream-foreign-object. private CommonAccessibility commonAccessibility; private CommonAural commonAural; @@ -74,6 +75,9 @@ public class InstreamForeignObject extends FObj { private Length width; // End of property values + //Additional value + private Point2D intrinsicDimensions; + /** * constructs an instream-foreign-object object (called by Maker). * @@ -280,4 +284,44 @@ public class InstreamForeignObject extends FObj { public int getNameId() { return FO_INSTREAM_FOREIGN_OBJECT; } + + /** + * Preloads the image so the intrinsic size is available. + */ + private void prepareIntrinsicSize() { + if (intrinsicDimensions == null) { + XMLObj child = (XMLObj)childNodes.get(0); + Point2D csize = new Point2D.Float(-1, -1); + intrinsicDimensions = child.getDimension(csize); + if (intrinsicDimensions == null) { + getLogger().error("Intrinsic dimensions of " + + " instream-foreign-object could not be determined"); + } + } + } + + /** + * @see org.apache.fop.fo.IntrinsicSizeAccess#getIntrinsicWidth() + */ + public int getIntrinsicWidth() { + prepareIntrinsicSize(); + if (intrinsicDimensions != null) { + return (int)(intrinsicDimensions.getX() * 1000); + } else { + return 0; + } + } + + /** + * @see org.apache.fop.fo.IntrinsicSizeAccess#getIntrinsicHeight() + */ + public int getIntrinsicHeight() { + prepareIntrinsicSize(); + if (intrinsicDimensions != null) { + return (int)(intrinsicDimensions.getY() * 1000); + } else { + return 0; + } + } + } diff --git a/src/java/org/apache/fop/layoutmgr/ExternalGraphicLayoutManager.java b/src/java/org/apache/fop/layoutmgr/ExternalGraphicLayoutManager.java index 033b131a8..bad48b8a1 100644 --- a/src/java/org/apache/fop/layoutmgr/ExternalGraphicLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/ExternalGraphicLayoutManager.java @@ -27,16 +27,14 @@ import org.apache.fop.area.inline.InlineArea; import org.apache.fop.area.inline.Viewport; import org.apache.fop.datatypes.Length; import org.apache.fop.fo.flow.ExternalGraphic; -import org.apache.fop.image.FopImage; -import org.apache.fop.image.ImageFactory; /** * LayoutManager for the fo:external-graphic formatting object */ public class ExternalGraphicLayoutManager extends LeafNodeLayoutManager { + private ExternalGraphic fobj; - private String url; private int breakAfter; private int breakBefore; private int align; @@ -70,8 +68,6 @@ public class ExternalGraphicLayoutManager extends LeafNodeLayoutManager { * @todo see if can simplify property handling logic */ private void setup() { - url = ImageFactory.getURL(fobj.getSrc()); - // assume lr-tb for now and just use the .optimum value of the range Length ipd = fobj.getInlineProgressionDimension().getOptimum().getLength(); if (ipd.getEnum() != EN_AUTO) { @@ -92,9 +88,6 @@ public class ExternalGraphicLayoutManager extends LeafNodeLayoutManager { } } - // if we need to load this image to get its size - FopImage fopimage = null; - int cwidth = -1; int cheight = -1; Length ch = fobj.getContentHeight(); @@ -120,35 +113,24 @@ public class ExternalGraphicLayoutManager extends LeafNodeLayoutManager { int scaling = fobj.getScaling(); if ((scaling == EN_UNIFORM) || (cwidth == -1) || cheight == -1) { - ImageFactory fact = ImageFactory.getInstance(); - fopimage = fact.getImage(url, fobj.getUserAgent()); - if (fopimage == null) { - // error - url = null; - return; - } - // load dimensions - if (!fopimage.load(FopImage.DIMENSIONS)) { - // error - url = null; - return; - } if (cwidth == -1 && cheight == -1) { - cwidth = (int)(fopimage.getWidth() * 1000); - cheight = (int)(fopimage.getHeight() * 1000); + cwidth = fobj.getIntrinsicWidth(); + cheight = fobj.getIntrinsicHeight(); } else if (cwidth == -1) { - cwidth = (int)(fopimage.getWidth() * cheight) / fopimage.getHeight(); + cwidth = (int)(fobj.getIntrinsicWidth() * (double)cheight + / fobj.getIntrinsicHeight()); } else if (cheight == -1) { - cheight = (int)(fopimage.getHeight() * cwidth) / fopimage.getWidth(); + cheight = (int)(fobj.getIntrinsicHeight() * (double)cwidth + / fobj.getIntrinsicWidth()); } else { // adjust the larger - double rat1 = cwidth / (fopimage.getWidth() * 1000f); - double rat2 = cheight / (fopimage.getHeight() * 1000f); + double rat1 = cwidth / fobj.getIntrinsicWidth(); + double rat2 = cheight / fobj.getIntrinsicHeight(); if (rat1 < rat2) { // reduce cheight - cheight = (int)(rat1 * fopimage.getHeight() * 1000); + cheight = (int)(rat1 * fobj.getIntrinsicHeight()); } else if (rat1 > rat2) { - cwidth = (int)(rat2 * fopimage.getWidth() * 1000); + cwidth = (int)(rat2 * fobj.getIntrinsicWidth()); } } } @@ -165,7 +147,7 @@ public class ExternalGraphicLayoutManager extends LeafNodeLayoutManager { if (overflow == EN_HIDDEN) { clip = true; } else if (overflow == EN_ERROR_IF_OVERFLOW) { - fobj.getLogger().error("Image: " + url + fobj.getLogger().error("Image: " + fobj.getURL() + " overflows the viewport, clipping to viewport"); clip = true; } diff --git a/src/java/org/apache/fop/layoutmgr/InstreamForeignObjectLM.java b/src/java/org/apache/fop/layoutmgr/InstreamForeignObjectLM.java index 15d87f848..dce3fa461 100644 --- a/src/java/org/apache/fop/layoutmgr/InstreamForeignObjectLM.java +++ b/src/java/org/apache/fop/layoutmgr/InstreamForeignObjectLM.java @@ -104,46 +104,46 @@ public class InstreamForeignObjectLM extends LeafNodeLayoutManager { int cheight = -1; len = fobj.getContentWidth(); if (len.getEnum() != EN_AUTO) { - /*if(len.scaleToFit()) { - if(ipd != -1) { + if (len.getEnum() == EN_SCALE_TO_FIT) { + if (ipd != -1) { cwidth = ipd; } - } else {*/ - cwidth = len.getValue(); + } else { + cwidth = len.getValue(); + } } len = fobj.getContentHeight(); if (len.getEnum() != EN_AUTO) { - /*if(len.scaleToFit()) { - if(bpd != -1) { + if (len.getEnum() == EN_SCALE_TO_FIT) { + if (bpd != -1) { cwidth = bpd; } - } else {*/ - cheight = len.getValue(); + } else { + cheight = len.getValue(); + } } - Point2D csize = new Point2D.Float(cwidth == -1 ? -1 : cwidth / 1000f, - cheight == -1 ? -1 : cheight / 1000f); - Point2D size = child.getDimension(csize); - if (size == null) { - // error - return null; - } - if (cwidth == -1) { - cwidth = (int)size.getX() * 1000; - } - if (cheight == -1) { - cheight = (int)size.getY() * 1000; - } int scaling = fobj.getScaling(); - if (scaling == EN_UNIFORM) { - // adjust the larger - double rat1 = cwidth / (size.getX() * 1000f); - double rat2 = cheight / (size.getY() * 1000f); - if (rat1 < rat2) { - // reduce cheight - cheight = (int)(rat1 * size.getY() * 1000); + if ((scaling == EN_UNIFORM) || (cwidth == -1) || cheight == -1) { + if (cwidth == -1 && cheight == -1) { + cwidth = fobj.getIntrinsicWidth(); + cheight = fobj.getIntrinsicHeight(); + } else if (cwidth == -1) { + cwidth = (int)(fobj.getIntrinsicWidth() * (double)cheight + / fobj.getIntrinsicHeight()); + } else if (cheight == -1) { + cheight = (int)(fobj.getIntrinsicHeight() * (double)cwidth + / fobj.getIntrinsicWidth()); } else { - cwidth = (int)(rat2 * size.getX() * 1000); + // adjust the larger + double rat1 = cwidth / fobj.getIntrinsicWidth(); + double rat2 = cheight / fobj.getIntrinsicHeight(); + if (rat1 < rat2) { + // reduce cheight + cheight = (int)(rat1 * fobj.getIntrinsicHeight()); + } else if (rat1 > rat2) { + cwidth = (int)(rat2 * fobj.getIntrinsicWidth()); + } } }