]> source.dussan.org Git - xmlgraphics-fop.git/commitdiff
Support for percentages on external-graphic and instream-foreign-object for the conte...
authorJeremias Maerki <jeremias@apache.org>
Tue, 28 Dec 2004 18:03:12 +0000 (18:03 +0000)
committerJeremias Maerki <jeremias@apache.org>
Tue, 28 Dec 2004 18:03:12 +0000 (18:03 +0000)
git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@198215 13f79535-47bb-0310-9956-ffa450edef68

src/java/org/apache/fop/datatypes/LengthBase.java
src/java/org/apache/fop/fo/FOPropertyMapping.java
src/java/org/apache/fop/fo/IntrinsicSizeAccess.java [new file with mode: 0644]
src/java/org/apache/fop/fo/flow/ExternalGraphic.java
src/java/org/apache/fop/fo/flow/InstreamForeignObject.java
src/java/org/apache/fop/layoutmgr/ExternalGraphicLayoutManager.java
src/java/org/apache/fop/layoutmgr/InstreamForeignObjectLM.java

index 45df34d8c471f92de13070bca6c2a9a7c7edb7d7..c6e229b89f62125d3d0230c65a3d29e551b0c31f 100644 (file)
@@ -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;
index 14878037f771570cb4b1c0e947a1bf0383cba0e5..127e2668de53b0f3ebd226ddf694d332391e925a 100644 (file)
@@ -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 (file)
index 0000000..07e2e2a
--- /dev/null
@@ -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();
+    
+}
index 55c5a567dba9631a5e284d6137337904a5992186..7d609028e77da11f2b22c077c493ddc3cea31d1f 100644 (file)
@@ -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;
+        }
+    }
+    
 }
index 60c36f2715462c51d4f69d2e4e82169b896f0c4e..f8ffccbd0fea1a5d9140fb7d27e61884b27a3053 100644 (file)
@@ -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;
+        }
+    }
+    
 }
index 033b131a8f45cfec260b28650226e7ad55d31a5a..bad48b8a1a691a5fc85bbcbb23f4acf05ada1e26 100644 (file)
@@ -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;
             }
index 15d87f84815d8ef3440d6bea6b2333d05bd90ba1..dce3fa4616b8c62b9135db26d2abd37aaf48a7ac 100644 (file)
@@ -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());
+                }
             }
         }