You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@poi.apache.org by jo...@apache.org on 2009/05/20 10:02:37 UTC

svn commit: r776607 [6/7] - in /poi/trunk/src/ooxml/java/org/apache/poi: ./ openxml4j/exceptions/ openxml4j/opc/ openxml4j/opc/internal/ openxml4j/opc/internal/marshallers/ openxml4j/opc/internal/signature/ openxml4j/opc/internal/unmarshallers/ openxml...

Modified: poi/trunk/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFPicture.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFPicture.java?rev=776607&r1=776606&r2=776607&view=diff
==============================================================================
--- poi/trunk/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFPicture.java (original)
+++ poi/trunk/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFPicture.java Wed May 20 08:02:35 2009
@@ -1,349 +1,350 @@
-/* ====================================================================
-   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.
-==================================================================== */
-package org.apache.poi.xssf.usermodel;
-
-import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.*;
-import org.openxmlformats.schemas.drawingml.x2006.main.*;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCol;
-import org.apache.poi.ss.usermodel.Workbook;
-import org.apache.poi.ss.usermodel.Picture;
-import org.apache.poi.util.POILogger;
-import org.apache.poi.util.POILogFactory;
-import org.apache.poi.POIXMLDocumentPart;
-import org.apache.poi.openxml4j.opc.PackageRelationship;
-import org.apache.poi.openxml4j.opc.PackagePart;
-import org.w3c.dom.NodeList;
-import org.w3c.dom.Element;
-import javax.imageio.ImageIO;
-import javax.imageio.ImageReader;
-import javax.imageio.stream.ImageInputStream;
-import java.awt.*;
-import java.awt.image.BufferedImage;
-import java.io.IOException;
-import java.util.Iterator;
-
-/**
- * Represents a picture shape in a SpreadsheetML drawing.
- *
- * @author Yegor Kozlov
- */
-public class XSSFPicture extends XSSFShape implements Picture {
-    private static final POILogger logger = POILogFactory.getLogger(XSSFPicture.class);
-
-    /**
-     * Column width measured as the number of characters of the maximum digit width of the
-     * numbers 0, 1, 2, ..., 9 as rendered in the normal style's font. There are 4 pixels of margin
-     * padding (two on each side), plus 1 pixel padding for the gridlines.
-     *
-     * This value is the same for default font in Office 2007 (Calibry) and Office 2003 and earlier (Arial)
-     */
-    private static float DEFAULT_COLUMN_WIDTH = 9.140625f;
-
-    /**
-     * A default instance of CTShape used for creating new shapes.
-     */
-    private static CTPicture prototype = null;
-
-    /**
-     * This object specifies a picture object and all its properties
-     */
-    private CTPicture ctPicture;
-
-    /**
-     * Construct a new XSSFPicture object. This constructor is called from
-     *  {@link XSSFDrawing#createPicture(XSSFClientAnchor, int)}
-     *
-     * @param drawing the XSSFDrawing that owns this picture
-     */
-    protected XSSFPicture(XSSFDrawing drawing, CTPicture ctPicture){
-        this.drawing = drawing;
-        this.ctPicture = ctPicture;
-    }
-
-    /**
-     * Returns a prototype that is used to construct new shapes
-     *
-     * @return a prototype that is used to construct new shapes
-     */
-    protected static CTPicture prototype(){
-        if(prototype == null) {
-            CTPicture pic = CTPicture.Factory.newInstance();
-            CTPictureNonVisual nvpr = pic.addNewNvPicPr();
-            CTNonVisualDrawingProps nvProps = nvpr.addNewCNvPr();
-            nvProps.setId(1);
-            nvProps.setName("Picture 1");
-            nvProps.setDescr("Picture");
-            CTNonVisualPictureProperties nvPicProps = nvpr.addNewCNvPicPr();
-            nvPicProps.addNewPicLocks().setNoChangeAspect(true);
-
-            CTBlipFillProperties blip = pic.addNewBlipFill();
-            blip.addNewBlip().setEmbed("");
-            blip.addNewStretch().addNewFillRect();
-
-            CTShapeProperties sppr = pic.addNewSpPr();
-            CTTransform2D t2d = sppr.addNewXfrm();
-            CTPositiveSize2D ext = t2d.addNewExt();
-            //should be original picture width and height expressed in EMUs
-            ext.setCx(0);
-            ext.setCy(0);
-
-            CTPoint2D off = t2d.addNewOff();
-            off.setX(0);
-            off.setY(0);
-
-            CTPresetGeometry2D prstGeom = sppr.addNewPrstGeom();
-            prstGeom.setPrst(STShapeType.RECT);
-            prstGeom.addNewAvLst();
-
-            prototype = pic;
-        }
-        return prototype;
-    }
-
-    /**
-     * Link this shape with the picture data
-     *
-     * @param rel relationship referring the picture data
-     */
-    protected void setPictureReference(PackageRelationship rel){
-        ctPicture.getBlipFill().getBlip().setEmbed(rel.getId());
-    }
-
-    /**
-     * Return the underlying CTPicture bean that holds all properties for this picture
-     *
-     * @return the underlying CTPicture bean
-     */
-    public CTPicture getCTPicture(){
-        return ctPicture;
-    }
-
-    /**
-     * Reset the image to the original size.
-     */
-    public void resize(){
-        resize(1.0);
-    }
-
-    /**
-     * Reset the image to the original size.
-     *
-     * @param scale the amount by which image dimensions are multiplied relative to the original size.
-     * <code>resize(1.0)</code> sets the original size, <code>resize(0.5)</code> resize to 50% of the original,
-     * <code>resize(2.0)</code> resizes to 200% of the original.
-     */
-    public void resize(double scale){
-        XSSFClientAnchor anchor = (XSSFClientAnchor)getAnchor();
-
-        XSSFClientAnchor pref = getPreferredSize(scale);
-
-        int row2 = anchor.getRow1() + (pref.getRow2() - pref.getRow1());
-        int col2 = anchor.getCol1() + (pref.getCol2() - pref.getCol1());
-
-        anchor.setCol2(col2);
-        anchor.setDx1(0);
-        anchor.setDx2(pref.getDx2());
-
-        anchor.setRow2(row2);
-        anchor.setDy1(0);
-        anchor.setDy2(pref.getDy2());
-    }
-
-    /**
-     * Calculate the preferred size for this picture.
-     *
-     * @return XSSFClientAnchor with the preferred size for this image
-     */
-    public XSSFClientAnchor getPreferredSize(){
-        return getPreferredSize(1);
-    }
-
-    /**
-     * Calculate the preferred size for this picture.
-     *
-     * @param scale the amount by which image dimensions are multiplied relative to the original size.
-     * @return XSSFClientAnchor with the preferred size for this image
-     */
-    public XSSFClientAnchor getPreferredSize(double scale){
-        XSSFClientAnchor anchor = (XSSFClientAnchor)getAnchor();
-
-        XSSFPictureData data = getPictureData();
-        Dimension size = getImageDimension(data.getPackagePart(), data.getPictureType());
-        double scaledWidth = size.getWidth() * scale;
-        double scaledHeight = size.getHeight() * scale;
-
-        float w = 0;
-        int col2 = anchor.getCol1();
-        int dx2 = 0;
-        if(anchor.getDx1() > 0){
-            w += getColumnWidthInPixels(col2) - anchor.getDx1();
-            col2++;
-        }
-
-        for (;;) {
-            w += getColumnWidthInPixels(col2);
-            if(w > scaledWidth) break;
-            col2++;
-        }
-
-        if(w > scaledWidth) {
-            double cw = getColumnWidthInPixels(col2 + 1);
-            double delta = w - scaledWidth;
-            dx2 = (int)(EMU_PER_PIXEL*(cw-delta));
-        }
-        anchor.setCol2(col2);
-        anchor.setDx2(dx2);
-
-        double h = 0;
-        int row2 = anchor.getRow1();
-        int dy2 = 0;
-
-        if(anchor.getDy1() > 0){
-            h += getRowHeightInPixels(row2) - anchor.getDy1();
-            row2++;
-        }
-
-        for (;;) {
-            h += getRowHeightInPixels(row2);
-            if(h > scaledHeight) break;
-            row2++;
-        }
-
-        if(h > scaledHeight) {
-            double ch = getRowHeightInPixels(row2 + 1);
-            double delta = h - scaledHeight;
-            dy2 = (int)(EMU_PER_PIXEL*(ch-delta));
-        }
-        anchor.setRow2(row2);
-        anchor.setDy2(dy2);
-
-        CTPositiveSize2D size2d =  ctPicture.getSpPr().getXfrm().getExt();
-        size2d.setCx((long)(scaledWidth*EMU_PER_PIXEL));
-        size2d.setCy((long)(scaledHeight*EMU_PER_PIXEL));
-
-        return anchor;
-    }
-
-    private float getColumnWidthInPixels(int columnIndex){
-        XSSFSheet sheet = (XSSFSheet)getDrawing().getParent();
-
-        CTCol col = sheet.getColumnHelper().getColumn(columnIndex, false);
-        double numChars = col == null || !col.isSetWidth() ? DEFAULT_COLUMN_WIDTH : col.getWidth();
-
-        return (float)numChars*XSSFWorkbook.DEFAULT_CHARACTER_WIDTH;
-    }
-
-    private float getRowHeightInPixels(int rowIndex){
-        XSSFSheet sheet = (XSSFSheet)getDrawing().getParent();
-
-        XSSFRow row = sheet.getRow(rowIndex);
-        float height = row != null ?  row.getHeightInPoints() : sheet.getDefaultRowHeightInPoints();
-        return height*PIXEL_DPI/POINT_DPI;
-    }
-
-    /**
-     * Return the dimension of this image
-     *
-     * @param part the package part holding raw picture data
-     * @param type type of the picture: {@link Workbook#PICTURE_TYPE_JPEG},
-     * {@link Workbook#PICTURE_TYPE_PNG} or {@link Workbook#PICTURE_TYPE_DIB}
-     *
-     * @return image dimension in pixels
-     */
-    protected static Dimension getImageDimension(PackagePart part, int type){
-        Dimension size = new Dimension();
-
-        switch (type){
-            //we can calculate the preferred size only for JPEG, PNG and BMP
-            //other formats like WMF, EMF and PICT are not supported in Java
-            case Workbook.PICTURE_TYPE_JPEG:
-            case Workbook.PICTURE_TYPE_PNG:
-            case Workbook.PICTURE_TYPE_DIB:
-                try {
-                    //read the image using javax.imageio.*
-                    ImageInputStream iis = ImageIO.createImageInputStream( part.getInputStream() );
-                    Iterator i = ImageIO.getImageReaders( iis );
-                    ImageReader r = (ImageReader) i.next();
-                    r.setInput( iis );
-                    BufferedImage img = r.read(0);
-
-                    int[] dpi = getResolution(r);
-
-                    //if DPI is zero then assume standard 96 DPI
-                    //since cannot divide by zero
-                    if (dpi[0] == 0) dpi[0] = PIXEL_DPI;
-                    if (dpi[1] == 0) dpi[1] = PIXEL_DPI;
-
-                    size.width = img.getWidth()*PIXEL_DPI/dpi[0];
-                    size.height = img.getHeight()*PIXEL_DPI/dpi[1];
-
-                } catch (IOException e){
-                    //silently return if ImageIO failed to read the image
-                    logger.log(POILogger.WARN, e);
-                }
-
-                break;
-            default:
-                logger.log(POILogger.WARN, "Only JPEG, PNG and DIB pictures can be automatically sized");
-        }
-        return size;
-    }
-
-    /**
-     * The metadata of PNG and JPEG can contain the width of a pixel in millimeters.
-     * Return the the "effective" dpi calculated as <code>25.4/HorizontalPixelSize</code>
-     * and <code>25.4/VerticalPixelSize</code>.  Where 25.4 is the number of mm in inch.
-     *
-     * @return array of two elements: <code>{horisontalPdi, verticalDpi}</code>.
-     * {96, 96} is the default.
-     */
-    protected static int[] getResolution(ImageReader r) throws IOException {
-        int hdpi = PIXEL_DPI, vdpi = PIXEL_DPI;
-        double mm2inch = 25.4;
-
-        NodeList lst;
-        Element node = (Element)r.getImageMetadata(0).getAsTree("javax_imageio_1.0");
-        lst = node.getElementsByTagName("HorizontalPixelSize");
-        if(lst != null && lst.getLength() == 1) hdpi = (int)(mm2inch/Float.parseFloat(((Element)lst.item(0)).getAttribute("value")));
-
-        lst = node.getElementsByTagName("VerticalPixelSize");
-        if(lst != null && lst.getLength() == 1) vdpi = (int)(mm2inch/Float.parseFloat(((Element)lst.item(0)).getAttribute("value")));
-
-        return new int[]{hdpi, vdpi};
-    }
-
-    /**
-     * Return picture data for this shape
-     *
-     * @return picture data for this shape
-     */
-    public XSSFPictureData getPictureData() {
-        String blipId = ctPicture.getBlipFill().getBlip().getEmbed();
-        for (POIXMLDocumentPart part : getDrawing().getRelations()) {
-            if(part.getPackageRelationship().getId().equals(blipId)){
-                return (XSSFPictureData)part;
-            }
-        }
-        logger.log(POILogger.WARN, "Picture data was not found for blipId=" + blipId);
-        return null;
-    }
-
-    protected CTShapeProperties getShapeProperties(){
-        return ctPicture.getSpPr();
-    }
-
-}
+/* ====================================================================
+   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.
+==================================================================== */
+
+package org.apache.poi.xssf.usermodel;
+
+import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.*;
+import org.openxmlformats.schemas.drawingml.x2006.main.*;
+import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCol;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.ss.usermodel.Picture;
+import org.apache.poi.util.POILogger;
+import org.apache.poi.util.POILogFactory;
+import org.apache.poi.POIXMLDocumentPart;
+import org.apache.poi.openxml4j.opc.PackageRelationship;
+import org.apache.poi.openxml4j.opc.PackagePart;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Element;
+import javax.imageio.ImageIO;
+import javax.imageio.ImageReader;
+import javax.imageio.stream.ImageInputStream;
+import java.awt.*;
+import java.awt.image.BufferedImage;
+import java.io.IOException;
+import java.util.Iterator;
+
+/**
+ * Represents a picture shape in a SpreadsheetML drawing.
+ *
+ * @author Yegor Kozlov
+ */
+public final class XSSFPicture extends XSSFShape implements Picture {
+    private static final POILogger logger = POILogFactory.getLogger(XSSFPicture.class);
+
+    /**
+     * Column width measured as the number of characters of the maximum digit width of the
+     * numbers 0, 1, 2, ..., 9 as rendered in the normal style's font. There are 4 pixels of margin
+     * padding (two on each side), plus 1 pixel padding for the gridlines.
+     *
+     * This value is the same for default font in Office 2007 (Calibry) and Office 2003 and earlier (Arial)
+     */
+    private static float DEFAULT_COLUMN_WIDTH = 9.140625f;
+
+    /**
+     * A default instance of CTShape used for creating new shapes.
+     */
+    private static CTPicture prototype = null;
+
+    /**
+     * This object specifies a picture object and all its properties
+     */
+    private CTPicture ctPicture;
+
+    /**
+     * Construct a new XSSFPicture object. This constructor is called from
+     *  {@link XSSFDrawing#createPicture(XSSFClientAnchor, int)}
+     *
+     * @param drawing the XSSFDrawing that owns this picture
+     */
+    protected XSSFPicture(XSSFDrawing drawing, CTPicture ctPicture){
+        this.drawing = drawing;
+        this.ctPicture = ctPicture;
+    }
+
+    /**
+     * Returns a prototype that is used to construct new shapes
+     *
+     * @return a prototype that is used to construct new shapes
+     */
+    protected static CTPicture prototype(){
+        if(prototype == null) {
+            CTPicture pic = CTPicture.Factory.newInstance();
+            CTPictureNonVisual nvpr = pic.addNewNvPicPr();
+            CTNonVisualDrawingProps nvProps = nvpr.addNewCNvPr();
+            nvProps.setId(1);
+            nvProps.setName("Picture 1");
+            nvProps.setDescr("Picture");
+            CTNonVisualPictureProperties nvPicProps = nvpr.addNewCNvPicPr();
+            nvPicProps.addNewPicLocks().setNoChangeAspect(true);
+
+            CTBlipFillProperties blip = pic.addNewBlipFill();
+            blip.addNewBlip().setEmbed("");
+            blip.addNewStretch().addNewFillRect();
+
+            CTShapeProperties sppr = pic.addNewSpPr();
+            CTTransform2D t2d = sppr.addNewXfrm();
+            CTPositiveSize2D ext = t2d.addNewExt();
+            //should be original picture width and height expressed in EMUs
+            ext.setCx(0);
+            ext.setCy(0);
+
+            CTPoint2D off = t2d.addNewOff();
+            off.setX(0);
+            off.setY(0);
+
+            CTPresetGeometry2D prstGeom = sppr.addNewPrstGeom();
+            prstGeom.setPrst(STShapeType.RECT);
+            prstGeom.addNewAvLst();
+
+            prototype = pic;
+        }
+        return prototype;
+    }
+
+    /**
+     * Link this shape with the picture data
+     *
+     * @param rel relationship referring the picture data
+     */
+    protected void setPictureReference(PackageRelationship rel){
+        ctPicture.getBlipFill().getBlip().setEmbed(rel.getId());
+    }
+
+    /**
+     * Return the underlying CTPicture bean that holds all properties for this picture
+     *
+     * @return the underlying CTPicture bean
+     */
+    public CTPicture getCTPicture(){
+        return ctPicture;
+    }
+
+    /**
+     * Reset the image to the original size.
+     */
+    public void resize(){
+        resize(1.0);
+    }
+
+    /**
+     * Reset the image to the original size.
+     *
+     * @param scale the amount by which image dimensions are multiplied relative to the original size.
+     * <code>resize(1.0)</code> sets the original size, <code>resize(0.5)</code> resize to 50% of the original,
+     * <code>resize(2.0)</code> resizes to 200% of the original.
+     */
+    public void resize(double scale){
+        XSSFClientAnchor anchor = (XSSFClientAnchor)getAnchor();
+
+        XSSFClientAnchor pref = getPreferredSize(scale);
+
+        int row2 = anchor.getRow1() + (pref.getRow2() - pref.getRow1());
+        int col2 = anchor.getCol1() + (pref.getCol2() - pref.getCol1());
+
+        anchor.setCol2(col2);
+        anchor.setDx1(0);
+        anchor.setDx2(pref.getDx2());
+
+        anchor.setRow2(row2);
+        anchor.setDy1(0);
+        anchor.setDy2(pref.getDy2());
+    }
+
+    /**
+     * Calculate the preferred size for this picture.
+     *
+     * @return XSSFClientAnchor with the preferred size for this image
+     */
+    public XSSFClientAnchor getPreferredSize(){
+        return getPreferredSize(1);
+    }
+
+    /**
+     * Calculate the preferred size for this picture.
+     *
+     * @param scale the amount by which image dimensions are multiplied relative to the original size.
+     * @return XSSFClientAnchor with the preferred size for this image
+     */
+    public XSSFClientAnchor getPreferredSize(double scale){
+        XSSFClientAnchor anchor = (XSSFClientAnchor)getAnchor();
+
+        XSSFPictureData data = getPictureData();
+        Dimension size = getImageDimension(data.getPackagePart(), data.getPictureType());
+        double scaledWidth = size.getWidth() * scale;
+        double scaledHeight = size.getHeight() * scale;
+
+        float w = 0;
+        int col2 = anchor.getCol1();
+        int dx2 = 0;
+        if(anchor.getDx1() > 0){
+            w += getColumnWidthInPixels(col2) - anchor.getDx1();
+            col2++;
+        }
+
+        for (;;) {
+            w += getColumnWidthInPixels(col2);
+            if(w > scaledWidth) break;
+            col2++;
+        }
+
+        if(w > scaledWidth) {
+            double cw = getColumnWidthInPixels(col2 + 1);
+            double delta = w - scaledWidth;
+            dx2 = (int)(EMU_PER_PIXEL*(cw-delta));
+        }
+        anchor.setCol2(col2);
+        anchor.setDx2(dx2);
+
+        double h = 0;
+        int row2 = anchor.getRow1();
+        int dy2 = 0;
+
+        if(anchor.getDy1() > 0){
+            h += getRowHeightInPixels(row2) - anchor.getDy1();
+            row2++;
+        }
+
+        for (;;) {
+            h += getRowHeightInPixels(row2);
+            if(h > scaledHeight) break;
+            row2++;
+        }
+
+        if(h > scaledHeight) {
+            double ch = getRowHeightInPixels(row2 + 1);
+            double delta = h - scaledHeight;
+            dy2 = (int)(EMU_PER_PIXEL*(ch-delta));
+        }
+        anchor.setRow2(row2);
+        anchor.setDy2(dy2);
+
+        CTPositiveSize2D size2d =  ctPicture.getSpPr().getXfrm().getExt();
+        size2d.setCx((long)(scaledWidth*EMU_PER_PIXEL));
+        size2d.setCy((long)(scaledHeight*EMU_PER_PIXEL));
+
+        return anchor;
+    }
+
+    private float getColumnWidthInPixels(int columnIndex){
+        XSSFSheet sheet = (XSSFSheet)getDrawing().getParent();
+
+        CTCol col = sheet.getColumnHelper().getColumn(columnIndex, false);
+        double numChars = col == null || !col.isSetWidth() ? DEFAULT_COLUMN_WIDTH : col.getWidth();
+
+        return (float)numChars*XSSFWorkbook.DEFAULT_CHARACTER_WIDTH;
+    }
+
+    private float getRowHeightInPixels(int rowIndex){
+        XSSFSheet sheet = (XSSFSheet)getDrawing().getParent();
+
+        XSSFRow row = sheet.getRow(rowIndex);
+        float height = row != null ?  row.getHeightInPoints() : sheet.getDefaultRowHeightInPoints();
+        return height*PIXEL_DPI/POINT_DPI;
+    }
+
+    /**
+     * Return the dimension of this image
+     *
+     * @param part the package part holding raw picture data
+     * @param type type of the picture: {@link Workbook#PICTURE_TYPE_JPEG},
+     * {@link Workbook#PICTURE_TYPE_PNG} or {@link Workbook#PICTURE_TYPE_DIB}
+     *
+     * @return image dimension in pixels
+     */
+    protected static Dimension getImageDimension(PackagePart part, int type){
+        Dimension size = new Dimension();
+
+        switch (type){
+            //we can calculate the preferred size only for JPEG, PNG and BMP
+            //other formats like WMF, EMF and PICT are not supported in Java
+            case Workbook.PICTURE_TYPE_JPEG:
+            case Workbook.PICTURE_TYPE_PNG:
+            case Workbook.PICTURE_TYPE_DIB:
+                try {
+                    //read the image using javax.imageio.*
+                    ImageInputStream iis = ImageIO.createImageInputStream( part.getInputStream() );
+                    Iterator i = ImageIO.getImageReaders( iis );
+                    ImageReader r = (ImageReader) i.next();
+                    r.setInput( iis );
+                    BufferedImage img = r.read(0);
+
+                    int[] dpi = getResolution(r);
+
+                    //if DPI is zero then assume standard 96 DPI
+                    //since cannot divide by zero
+                    if (dpi[0] == 0) dpi[0] = PIXEL_DPI;
+                    if (dpi[1] == 0) dpi[1] = PIXEL_DPI;
+
+                    size.width = img.getWidth()*PIXEL_DPI/dpi[0];
+                    size.height = img.getHeight()*PIXEL_DPI/dpi[1];
+
+                } catch (IOException e){
+                    //silently return if ImageIO failed to read the image
+                    logger.log(POILogger.WARN, e);
+                }
+
+                break;
+            default:
+                logger.log(POILogger.WARN, "Only JPEG, PNG and DIB pictures can be automatically sized");
+        }
+        return size;
+    }
+
+    /**
+     * The metadata of PNG and JPEG can contain the width of a pixel in millimeters.
+     * Return the the "effective" dpi calculated as <code>25.4/HorizontalPixelSize</code>
+     * and <code>25.4/VerticalPixelSize</code>.  Where 25.4 is the number of mm in inch.
+     *
+     * @return array of two elements: <code>{horisontalPdi, verticalDpi}</code>.
+     * {96, 96} is the default.
+     */
+    protected static int[] getResolution(ImageReader r) throws IOException {
+        int hdpi = PIXEL_DPI, vdpi = PIXEL_DPI;
+        double mm2inch = 25.4;
+
+        NodeList lst;
+        Element node = (Element)r.getImageMetadata(0).getAsTree("javax_imageio_1.0");
+        lst = node.getElementsByTagName("HorizontalPixelSize");
+        if(lst != null && lst.getLength() == 1) hdpi = (int)(mm2inch/Float.parseFloat(((Element)lst.item(0)).getAttribute("value")));
+
+        lst = node.getElementsByTagName("VerticalPixelSize");
+        if(lst != null && lst.getLength() == 1) vdpi = (int)(mm2inch/Float.parseFloat(((Element)lst.item(0)).getAttribute("value")));
+
+        return new int[]{hdpi, vdpi};
+    }
+
+    /**
+     * Return picture data for this shape
+     *
+     * @return picture data for this shape
+     */
+    public XSSFPictureData getPictureData() {
+        String blipId = ctPicture.getBlipFill().getBlip().getEmbed();
+        for (POIXMLDocumentPart part : getDrawing().getRelations()) {
+            if(part.getPackageRelationship().getId().equals(blipId)){
+                return (XSSFPictureData)part;
+            }
+        }
+        logger.log(POILogger.WARN, "Picture data was not found for blipId=" + blipId);
+        return null;
+    }
+
+    protected CTShapeProperties getShapeProperties(){
+        return ctPicture.getSpPr();
+    }
+
+}

Modified: poi/trunk/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFShape.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFShape.java?rev=776607&r1=776606&r2=776607&view=diff
==============================================================================
--- poi/trunk/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFShape.java (original)
+++ poi/trunk/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFShape.java Wed May 20 08:02:35 2009
@@ -1,150 +1,151 @@
-/* ====================================================================
-   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.
-==================================================================== */
-package org.apache.poi.xssf.usermodel;
-
-import org.openxmlformats.schemas.drawingml.x2006.main.*;
-
-/**
- * Represents a shape in a SpreadsheetML drawing.
- *
- * @author Yegor Kozlov
- */
-public abstract class XSSFShape {
-    public static final int EMU_PER_PIXEL = 9525;
-    public static final int EMU_PER_POINT = 12700;
-
-    public static final int POINT_DPI = 72;
-    public static final int PIXEL_DPI = 96;
-
-    /**
-     * Parent drawing
-     */
-    protected XSSFDrawing drawing;
-
-    /**
-     * The parent shape, always not-null for shapes in groups
-     */
-    protected XSSFShapeGroup parent;
-
-    /**
-     * anchor that is used by this shape
-     */
-    protected XSSFAnchor anchor;
-
-    /**
-     * Return the drawing that owns this shape
-     *
-     * @return the parent drawing that owns this shape
-     */
-    public XSSFDrawing getDrawing(){
-        return drawing;
-    }
-
-    /**
-     * Gets the parent shape.
-     */
-    public XSSFShapeGroup getParent()
-    {
-        return parent;
-    }
-
-    /**
-     * @return  the anchor that is used by this shape.
-     */
-    public XSSFAnchor getAnchor()
-    {
-        return anchor;
-    }
-
-    /**
-     * Returns xml bean with shape properties. 
-     *
-     * @return xml bean with shape properties.
-     */
-    protected abstract CTShapeProperties getShapeProperties();
-
-    /**
-     * Whether this shape is not filled with a color
-     *
-     * @return true if this shape is not filled with a color.
-     */
-    public boolean isNoFill() {
-        return getShapeProperties().isSetNoFill();
-    }
-
-    /**
-     * Sets whether this shape is filled or transparent.
-     *
-     * @param noFill if true then no fill will be applied to the shape element.
-     */
-    public void setNoFill(boolean noFill) {
-        CTShapeProperties props = getShapeProperties();
-        //unset solid and pattern fills if they are set
-        if (props.isSetPattFill()) props.unsetPattFill();
-        if (props.isSetSolidFill()) props.unsetSolidFill();
-
-        props.setNoFill(CTNoFillProperties.Factory.newInstance());
-    }
-
-    /**
-     * Sets the color used to fill this shape using the solid fill pattern.
-     */
-    public void setFillColor(int red, int green, int blue) {
-        CTShapeProperties props = getShapeProperties();
-        CTSolidColorFillProperties fill = props.isSetSolidFill() ? props.getSolidFill() : props.addNewSolidFill();
-        CTSRgbColor rgb = CTSRgbColor.Factory.newInstance();
-        rgb.setVal(new byte[]{(byte)red, (byte)green, (byte)blue});
-        fill.setSrgbClr(rgb);
-    }
-
-    /**
-     * The color applied to the lines of this shape.
-     */
-    public void setLineStyleColor( int red, int green, int blue ) {
-        CTShapeProperties props = getShapeProperties();
-        CTLineProperties ln = props.isSetLn() ? props.getLn() : props.addNewLn();
-        CTSolidColorFillProperties fill = ln.isSetSolidFill() ? ln.getSolidFill() : ln.addNewSolidFill();
-        CTSRgbColor rgb = CTSRgbColor.Factory.newInstance();
-        rgb.setVal(new byte[]{(byte)red, (byte)green, (byte)blue});
-        fill.setSrgbClr(rgb);
-    }
-
-    /**
-     * Specifies the width to be used for the underline stroke.
-     *
-     * @param lineWidth width in points
-     */
-    public void setLineWidth( double lineWidth ) {
-        CTShapeProperties props = getShapeProperties();
-        CTLineProperties ln = props.isSetLn() ? props.getLn() : props.addNewLn();
-        ln.setW((int)(lineWidth*EMU_PER_POINT));
-    }
-
-    /**
-     * Sets the line style.
-     *
-     * @param lineStyle
-     */
-    public void setLineStyle( int lineStyle ) {
-        CTShapeProperties props = getShapeProperties();
-        CTLineProperties ln = props.isSetLn() ? props.getLn() : props.addNewLn();
-        CTPresetLineDashProperties dashStyle = CTPresetLineDashProperties.Factory.newInstance();
-        dashStyle.setVal(STPresetLineDashVal.Enum.forInt(lineStyle+1));
-        ln.setPrstDash(dashStyle);
-    }
-
-}
+/* ====================================================================
+   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.
+==================================================================== */
+
+package org.apache.poi.xssf.usermodel;
+
+import org.openxmlformats.schemas.drawingml.x2006.main.*;
+
+/**
+ * Represents a shape in a SpreadsheetML drawing.
+ *
+ * @author Yegor Kozlov
+ */
+public abstract class XSSFShape {
+    public static final int EMU_PER_PIXEL = 9525;
+    public static final int EMU_PER_POINT = 12700;
+
+    public static final int POINT_DPI = 72;
+    public static final int PIXEL_DPI = 96;
+
+    /**
+     * Parent drawing
+     */
+    protected XSSFDrawing drawing;
+
+    /**
+     * The parent shape, always not-null for shapes in groups
+     */
+    protected XSSFShapeGroup parent;
+
+    /**
+     * anchor that is used by this shape
+     */
+    protected XSSFAnchor anchor;
+
+    /**
+     * Return the drawing that owns this shape
+     *
+     * @return the parent drawing that owns this shape
+     */
+    public XSSFDrawing getDrawing(){
+        return drawing;
+    }
+
+    /**
+     * Gets the parent shape.
+     */
+    public XSSFShapeGroup getParent()
+    {
+        return parent;
+    }
+
+    /**
+     * @return  the anchor that is used by this shape.
+     */
+    public XSSFAnchor getAnchor()
+    {
+        return anchor;
+    }
+
+    /**
+     * Returns xml bean with shape properties.
+     *
+     * @return xml bean with shape properties.
+     */
+    protected abstract CTShapeProperties getShapeProperties();
+
+    /**
+     * Whether this shape is not filled with a color
+     *
+     * @return true if this shape is not filled with a color.
+     */
+    public boolean isNoFill() {
+        return getShapeProperties().isSetNoFill();
+    }
+
+    /**
+     * Sets whether this shape is filled or transparent.
+     *
+     * @param noFill if true then no fill will be applied to the shape element.
+     */
+    public void setNoFill(boolean noFill) {
+        CTShapeProperties props = getShapeProperties();
+        //unset solid and pattern fills if they are set
+        if (props.isSetPattFill()) props.unsetPattFill();
+        if (props.isSetSolidFill()) props.unsetSolidFill();
+
+        props.setNoFill(CTNoFillProperties.Factory.newInstance());
+    }
+
+    /**
+     * Sets the color used to fill this shape using the solid fill pattern.
+     */
+    public void setFillColor(int red, int green, int blue) {
+        CTShapeProperties props = getShapeProperties();
+        CTSolidColorFillProperties fill = props.isSetSolidFill() ? props.getSolidFill() : props.addNewSolidFill();
+        CTSRgbColor rgb = CTSRgbColor.Factory.newInstance();
+        rgb.setVal(new byte[]{(byte)red, (byte)green, (byte)blue});
+        fill.setSrgbClr(rgb);
+    }
+
+    /**
+     * The color applied to the lines of this shape.
+     */
+    public void setLineStyleColor( int red, int green, int blue ) {
+        CTShapeProperties props = getShapeProperties();
+        CTLineProperties ln = props.isSetLn() ? props.getLn() : props.addNewLn();
+        CTSolidColorFillProperties fill = ln.isSetSolidFill() ? ln.getSolidFill() : ln.addNewSolidFill();
+        CTSRgbColor rgb = CTSRgbColor.Factory.newInstance();
+        rgb.setVal(new byte[]{(byte)red, (byte)green, (byte)blue});
+        fill.setSrgbClr(rgb);
+    }
+
+    /**
+     * Specifies the width to be used for the underline stroke.
+     *
+     * @param lineWidth width in points
+     */
+    public void setLineWidth( double lineWidth ) {
+        CTShapeProperties props = getShapeProperties();
+        CTLineProperties ln = props.isSetLn() ? props.getLn() : props.addNewLn();
+        ln.setW((int)(lineWidth*EMU_PER_POINT));
+    }
+
+    /**
+     * Sets the line style.
+     *
+     * @param lineStyle
+     */
+    public void setLineStyle( int lineStyle ) {
+        CTShapeProperties props = getShapeProperties();
+        CTLineProperties ln = props.isSetLn() ? props.getLn() : props.addNewLn();
+        CTPresetLineDashProperties dashStyle = CTPresetLineDashProperties.Factory.newInstance();
+        dashStyle.setVal(STPresetLineDashVal.Enum.forInt(lineStyle+1));
+        ln.setPrstDash(dashStyle);
+    }
+
+}

Modified: poi/trunk/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFShapeGroup.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFShapeGroup.java?rev=776607&r1=776606&r2=776607&view=diff
==============================================================================
--- poi/trunk/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFShapeGroup.java (original)
+++ poi/trunk/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFShapeGroup.java Wed May 20 08:02:35 2009
@@ -1,185 +1,186 @@
-/* ====================================================================
-   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.
-==================================================================== */
-package org.apache.poi.xssf.usermodel;
-
-import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.*;
-import org.openxmlformats.schemas.drawingml.x2006.main.*;
-import org.apache.poi.openxml4j.opc.PackageRelationship;
-
-/**
- * This object specifies a group shape that represents many shapes grouped together. This shape is to be treated
- * just as if it were a regular shape but instead of being described by a single geometry it is made up of all the
- * shape geometries encompassed within it. Within a group shape each of the shapes that make up the group are
- * specified just as they normally would.
- *
- * @author Yegor Kozlov
- */
-public class XSSFShapeGroup extends XSSFShape {
-    private static CTGroupShape prototype = null;
-
-    private CTGroupShape ctGroup;
-
-    /**
-     * Construct a new XSSFSimpleShape object.
-     *
-     * @param drawing the XSSFDrawing that owns this shape
-     * @param ctGroup the XML bean that stores this group content
-     */
-    protected XSSFShapeGroup(XSSFDrawing drawing, CTGroupShape ctGroup) {
-        this.drawing = drawing;
-        this.ctGroup = ctGroup;
-    }
-
-    /**
-     * Initialize default structure of a new shape group
-     */
-    protected static CTGroupShape prototype() {
-        if (prototype == null) {
-            CTGroupShape shape = CTGroupShape.Factory.newInstance();
-
-            CTGroupShapeNonVisual nv = shape.addNewNvGrpSpPr();
-            CTNonVisualDrawingProps nvpr = nv.addNewCNvPr();
-            nvpr.setId(0);
-            nvpr.setName("Group 0");
-            nv.addNewCNvGrpSpPr();
-            CTGroupShapeProperties sp = shape.addNewGrpSpPr();
-            CTGroupTransform2D t2d = sp.addNewXfrm();
-            CTPositiveSize2D p1 = t2d.addNewExt();
-            p1.setCx(0);
-            p1.setCy(0);
-            CTPoint2D p2 = t2d.addNewOff();
-            p2.setX(0);
-            p2.setY(0);
-            CTPositiveSize2D p3 = t2d.addNewChExt();
-            p3.setCx(0);
-            p3.setCy(0);
-            CTPoint2D p4 = t2d.addNewChOff();
-            p4.setX(0);
-            p4.setY(0);
-
-            prototype = shape;
-        }
-        return prototype;
-    }
-
-    /**
-     * Constructs a textbox.
-     *
-     * @param anchor the child anchor describes how this shape is attached
-     *               to the group.
-     * @return      the newly created textbox.
-     */
-    public XSSFTextBox createTextbox(XSSFChildAnchor anchor){
-        CTShape ctShape = ctGroup.addNewSp();
-        ctShape.set(XSSFSimpleShape.prototype());
-
-        XSSFTextBox shape = new XSSFTextBox(getDrawing(), ctShape);
-        shape.parent = this;
-        shape.anchor = anchor;
-        shape.getCTShape().getSpPr().setXfrm(anchor.getCTTransform2D());
-        return shape;
-
-    }
-    /**
-     * Creates a simple shape.  This includes such shapes as lines, rectangles,
-     * and ovals.
-     *
-     * @param anchor the child anchor describes how this shape is attached
-     *               to the group.
-     * @return the newly created shape.
-     */
-    public XSSFSimpleShape createSimpleShape(XSSFChildAnchor anchor) {
-        CTShape ctShape = ctGroup.addNewSp();
-        ctShape.set(XSSFSimpleShape.prototype());
-
-        XSSFSimpleShape shape = new XSSFSimpleShape(getDrawing(), ctShape);
-        shape.parent = this;
-        shape.anchor = anchor;
-        shape.getCTShape().getSpPr().setXfrm(anchor.getCTTransform2D());
-        return shape;
-    }
-
-    /**
-     * Creates a simple shape.  This includes such shapes as lines, rectangles,
-     * and ovals.
-     *
-     * @param anchor the child anchor describes how this shape is attached
-     *               to the group.
-     * @return the newly created shape.
-     */
-    public XSSFConnector createConnector(XSSFChildAnchor anchor) {
-        CTConnector ctShape = ctGroup.addNewCxnSp();
-        ctShape.set(XSSFConnector.prototype());
-
-        XSSFConnector shape = new XSSFConnector(getDrawing(), ctShape);
-        shape.parent = this;
-        shape.anchor = anchor;
-        shape.getCTConnector().getSpPr().setXfrm(anchor.getCTTransform2D());
-        return shape;
-    }
-
-    /**
-     * Creates a picture.
-     *
-     * @param anchor       the client anchor describes how this picture is attached to the sheet.
-     * @param pictureIndex the index of the picture in the workbook collection of pictures,
-     *                     {@link XSSFWorkbook#getAllPictures()} .
-     * @return the newly created picture shape.
-     */
-    public XSSFPicture createPicture(XSSFClientAnchor anchor, int pictureIndex) {
-        PackageRelationship rel = getDrawing().addPictureReference(pictureIndex);
-
-        CTPicture ctShape = ctGroup.addNewPic();
-        ctShape.set(XSSFPicture.prototype());
-
-        XSSFPicture shape = new XSSFPicture(getDrawing(), ctShape);
-        shape.parent = this;
-        shape.anchor = anchor;
-        shape.setPictureReference(rel);
-        return shape;
-    }
-
-    public CTGroupShape getCTGroupShape() {
-        return ctGroup;
-    }
-
-    /**
-     * Sets the coordinate space of this group.  All children are constrained
-     * to these coordinates.
-     */
-    public void setCoordinates(int x1, int y1, int x2, int y2) {
-        CTGroupTransform2D t2d = ctGroup.getGrpSpPr().getXfrm();
-        CTPoint2D off = t2d.getOff();
-        off.setX(x1);
-        off.setY(y1);
-        CTPositiveSize2D ext = t2d.getExt();
-        ext.setCx(x2);
-        ext.setCy(y2);
-
-        CTPoint2D chOff = t2d.getChOff();
-        chOff.setX(x1);
-        chOff.setY(y1);
-        CTPositiveSize2D chExt = t2d.getChExt();
-        chExt.setCx(x2);
-        chExt.setCy(y2);
-    }
-
-    protected CTShapeProperties getShapeProperties() {
-        throw new IllegalStateException("Not supported for shape group");
-    }
-
-}
+/* ====================================================================
+   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.
+==================================================================== */
+
+package org.apache.poi.xssf.usermodel;
+
+import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.*;
+import org.openxmlformats.schemas.drawingml.x2006.main.*;
+import org.apache.poi.openxml4j.opc.PackageRelationship;
+
+/**
+ * This object specifies a group shape that represents many shapes grouped together. This shape is to be treated
+ * just as if it were a regular shape but instead of being described by a single geometry it is made up of all the
+ * shape geometries encompassed within it. Within a group shape each of the shapes that make up the group are
+ * specified just as they normally would.
+ *
+ * @author Yegor Kozlov
+ */
+public final class XSSFShapeGroup extends XSSFShape {
+    private static CTGroupShape prototype = null;
+
+    private CTGroupShape ctGroup;
+
+    /**
+     * Construct a new XSSFSimpleShape object.
+     *
+     * @param drawing the XSSFDrawing that owns this shape
+     * @param ctGroup the XML bean that stores this group content
+     */
+    protected XSSFShapeGroup(XSSFDrawing drawing, CTGroupShape ctGroup) {
+        this.drawing = drawing;
+        this.ctGroup = ctGroup;
+    }
+
+    /**
+     * Initialize default structure of a new shape group
+     */
+    protected static CTGroupShape prototype() {
+        if (prototype == null) {
+            CTGroupShape shape = CTGroupShape.Factory.newInstance();
+
+            CTGroupShapeNonVisual nv = shape.addNewNvGrpSpPr();
+            CTNonVisualDrawingProps nvpr = nv.addNewCNvPr();
+            nvpr.setId(0);
+            nvpr.setName("Group 0");
+            nv.addNewCNvGrpSpPr();
+            CTGroupShapeProperties sp = shape.addNewGrpSpPr();
+            CTGroupTransform2D t2d = sp.addNewXfrm();
+            CTPositiveSize2D p1 = t2d.addNewExt();
+            p1.setCx(0);
+            p1.setCy(0);
+            CTPoint2D p2 = t2d.addNewOff();
+            p2.setX(0);
+            p2.setY(0);
+            CTPositiveSize2D p3 = t2d.addNewChExt();
+            p3.setCx(0);
+            p3.setCy(0);
+            CTPoint2D p4 = t2d.addNewChOff();
+            p4.setX(0);
+            p4.setY(0);
+
+            prototype = shape;
+        }
+        return prototype;
+    }
+
+    /**
+     * Constructs a textbox.
+     *
+     * @param anchor the child anchor describes how this shape is attached
+     *               to the group.
+     * @return      the newly created textbox.
+     */
+    public XSSFTextBox createTextbox(XSSFChildAnchor anchor){
+        CTShape ctShape = ctGroup.addNewSp();
+        ctShape.set(XSSFSimpleShape.prototype());
+
+        XSSFTextBox shape = new XSSFTextBox(getDrawing(), ctShape);
+        shape.parent = this;
+        shape.anchor = anchor;
+        shape.getCTShape().getSpPr().setXfrm(anchor.getCTTransform2D());
+        return shape;
+
+    }
+    /**
+     * Creates a simple shape.  This includes such shapes as lines, rectangles,
+     * and ovals.
+     *
+     * @param anchor the child anchor describes how this shape is attached
+     *               to the group.
+     * @return the newly created shape.
+     */
+    public XSSFSimpleShape createSimpleShape(XSSFChildAnchor anchor) {
+        CTShape ctShape = ctGroup.addNewSp();
+        ctShape.set(XSSFSimpleShape.prototype());
+
+        XSSFSimpleShape shape = new XSSFSimpleShape(getDrawing(), ctShape);
+        shape.parent = this;
+        shape.anchor = anchor;
+        shape.getCTShape().getSpPr().setXfrm(anchor.getCTTransform2D());
+        return shape;
+    }
+
+    /**
+     * Creates a simple shape.  This includes such shapes as lines, rectangles,
+     * and ovals.
+     *
+     * @param anchor the child anchor describes how this shape is attached
+     *               to the group.
+     * @return the newly created shape.
+     */
+    public XSSFConnector createConnector(XSSFChildAnchor anchor) {
+        CTConnector ctShape = ctGroup.addNewCxnSp();
+        ctShape.set(XSSFConnector.prototype());
+
+        XSSFConnector shape = new XSSFConnector(getDrawing(), ctShape);
+        shape.parent = this;
+        shape.anchor = anchor;
+        shape.getCTConnector().getSpPr().setXfrm(anchor.getCTTransform2D());
+        return shape;
+    }
+
+    /**
+     * Creates a picture.
+     *
+     * @param anchor       the client anchor describes how this picture is attached to the sheet.
+     * @param pictureIndex the index of the picture in the workbook collection of pictures,
+     *                     {@link XSSFWorkbook#getAllPictures()} .
+     * @return the newly created picture shape.
+     */
+    public XSSFPicture createPicture(XSSFClientAnchor anchor, int pictureIndex) {
+        PackageRelationship rel = getDrawing().addPictureReference(pictureIndex);
+
+        CTPicture ctShape = ctGroup.addNewPic();
+        ctShape.set(XSSFPicture.prototype());
+
+        XSSFPicture shape = new XSSFPicture(getDrawing(), ctShape);
+        shape.parent = this;
+        shape.anchor = anchor;
+        shape.setPictureReference(rel);
+        return shape;
+    }
+
+    public CTGroupShape getCTGroupShape() {
+        return ctGroup;
+    }
+
+    /**
+     * Sets the coordinate space of this group.  All children are constrained
+     * to these coordinates.
+     */
+    public void setCoordinates(int x1, int y1, int x2, int y2) {
+        CTGroupTransform2D t2d = ctGroup.getGrpSpPr().getXfrm();
+        CTPoint2D off = t2d.getOff();
+        off.setX(x1);
+        off.setY(y1);
+        CTPositiveSize2D ext = t2d.getExt();
+        ext.setCx(x2);
+        ext.setCy(y2);
+
+        CTPoint2D chOff = t2d.getChOff();
+        chOff.setX(x1);
+        chOff.setY(y1);
+        CTPositiveSize2D chExt = t2d.getChExt();
+        chExt.setCx(x2);
+        chExt.setCy(y2);
+    }
+
+    protected CTShapeProperties getShapeProperties() {
+        throw new IllegalStateException("Not supported for shape group");
+    }
+
+}

Modified: poi/trunk/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSimpleShape.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSimpleShape.java?rev=776607&r1=776606&r2=776607&view=diff
==============================================================================
--- poi/trunk/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSimpleShape.java (original)
+++ poi/trunk/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSimpleShape.java Wed May 20 08:02:35 2009
@@ -1,179 +1,180 @@
-/* ====================================================================
-   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.
-==================================================================== */
-package org.apache.poi.xssf.usermodel;
-
-import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTShape;
-import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTShapeNonVisual;
-import org.openxmlformats.schemas.drawingml.x2006.main.*;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.*;
-
-/**
- * Represents a shape with a predefined geometry in a SpreadsheetML drawing.
- * Possible shape types are defined in {@link org.apache.poi.ss.usermodel.ShapeTypes}
- *
- * @author Yegor Kozlov
- */
-public class XSSFSimpleShape extends XSSFShape {
-    /**
-     * A default instance of CTShape used for creating new shapes.
-     */
-    private static CTShape prototype = null;
-
-    /**
-     *  Xml bean that stores properties of this shape
-     */
-    private CTShape ctShape;
-
-    protected XSSFSimpleShape(XSSFDrawing drawing, CTShape ctShape) {
-        this.drawing = drawing;
-        this.ctShape = ctShape;
-    }
-
-    /**
-     * Prototype with the default structure of a new auto-shape.
-     */
-    protected static CTShape prototype() {
-        if(prototype == null) {
-            CTShape shape = CTShape.Factory.newInstance();
-
-            CTShapeNonVisual nv = shape.addNewNvSpPr();
-            CTNonVisualDrawingProps nvp = nv.addNewCNvPr();
-            nvp.setId(1);
-            nvp.setName("Shape 1");
-            nv.addNewCNvSpPr();
-
-            CTShapeProperties sp = shape.addNewSpPr();
-            CTTransform2D t2d = sp.addNewXfrm();
-            CTPositiveSize2D p1 = t2d.addNewExt();
-            p1.setCx(0);
-            p1.setCy(0);
-            CTPoint2D p2 = t2d.addNewOff();
-            p2.setX(0);
-            p2.setY(0);
-
-            CTPresetGeometry2D geom = sp.addNewPrstGeom();
-            geom.setPrst(STShapeType.RECT);
-            geom.addNewAvLst();
-
-            CTShapeStyle style = shape.addNewStyle();
-            CTSchemeColor scheme = style.addNewLnRef().addNewSchemeClr();
-            scheme.setVal(STSchemeColorVal.ACCENT_1);
-            scheme.addNewShade().setVal(50000);
-            style.getLnRef().setIdx(2);
-
-            CTStyleMatrixReference fillref = style.addNewFillRef();
-            fillref.setIdx(1);
-            fillref.addNewSchemeClr().setVal(STSchemeColorVal.ACCENT_1);
-
-            CTStyleMatrixReference effectRef = style.addNewEffectRef();
-            effectRef.setIdx(0);
-            effectRef.addNewSchemeClr().setVal(STSchemeColorVal.ACCENT_1);
-
-            CTFontReference fontRef = style.addNewFontRef();
-            fontRef.setIdx(STFontCollectionIndex.MINOR);
-            fontRef.addNewSchemeClr().setVal(STSchemeColorVal.LT_1);
-
-            CTTextBody body = shape.addNewTxBody();
-            CTTextBodyProperties bodypr = body.addNewBodyPr();
-            bodypr.setAnchor(STTextAnchoringType.CTR);
-            bodypr.setRtlCol(false);
-            CTTextParagraph p = body.addNewP();
-            p.addNewPPr().setAlgn(STTextAlignType.CTR);
-            CTTextCharacterProperties endPr = p.addNewEndParaRPr();
-            endPr.setLang("en-US");
-            endPr.setSz(1100);
-
-            body.addNewLstStyle();
-
-            prototype = shape;
-        }
-        return prototype;
-    }
-
-    public CTShape getCTShape(){
-        return ctShape;
-    }
-
-    /**
-     * Gets the shape type, one of the constants defined in {@link org.apache.poi.ss.usermodel.ShapeTypes}.
-     *
-     * @return the shape type
-     * @see org.apache.poi.ss.usermodel.ShapeTypes
-     */
-    public int getShapeType() {
-        return ctShape.getSpPr().getPrstGeom().getPrst().intValue();
-    }
-
-    /**
-     * Sets the shape types.
-     *
-     * @param type the shape type, one of the constants defined in {@link org.apache.poi.ss.usermodel.ShapeTypes}.
-     * @see org.apache.poi.ss.usermodel.ShapeTypes
-     */
-    public void setShapeType(int type) {
-        ctShape.getSpPr().getPrstGeom().setPrst(STShapeType.Enum.forInt(type));
-    }
-
-    protected CTShapeProperties getShapeProperties(){
-        return ctShape.getSpPr();
-    }
-
-    public void setText(XSSFRichTextString str){
-
-        XSSFWorkbook wb = (XSSFWorkbook)getDrawing().getParent().getParent();
-        str.setStylesTableReference(wb.getStylesSource());
-
-        CTTextParagraph p = CTTextParagraph.Factory.newInstance();
-        if(str.numFormattingRuns() == 0){
-            CTRegularTextRun r = p.addNewR();
-            CTTextCharacterProperties rPr = r.addNewRPr();
-            rPr.setLang("en-US");
-            rPr.setSz(1100);
-            r.setT(str.getString());
-
-        } else {
-            for (int i = 0; i < str.getCTRst().sizeOfRArray(); i++) {
-                CTRElt lt = str.getCTRst().getRArray(i);
-                CTRPrElt ltPr = lt.getRPr();
-
-                CTRegularTextRun r = p.addNewR();
-                CTTextCharacterProperties rPr = r.addNewRPr();
-                rPr.setLang("en-US");
-
-                applyAttributes(ltPr, rPr);
-
-                r.setT(lt.getT());
-            }
-        }
-        ctShape.getTxBody().setPArray(new CTTextParagraph[]{p});
-
-    }
-
-    /**
-     *
-     * CTRPrElt --> CTFont adapter
-     */
-    private static void applyAttributes(CTRPrElt pr, CTTextCharacterProperties rPr){
-
-        if(pr.sizeOfBArray() > 0) rPr.setB(pr.getBArray(0).getVal());
-        //if(pr.sizeOfUArray() > 0) rPr.setU(pr.getUArray(0).getVal());
-        if(pr.sizeOfIArray() > 0) rPr.setI(pr.getIArray(0).getVal());
-
-        CTTextFont rFont = rPr.addNewLatin();
-        rFont.setTypeface(pr.sizeOfRFontArray() > 0 ? pr.getRFontArray(0).getVal() : "Arial");
-    }
-}
+/* ====================================================================
+   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.
+==================================================================== */
+
+package org.apache.poi.xssf.usermodel;
+
+import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTShape;
+import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTShapeNonVisual;
+import org.openxmlformats.schemas.drawingml.x2006.main.*;
+import org.openxmlformats.schemas.spreadsheetml.x2006.main.*;
+
+/**
+ * Represents a shape with a predefined geometry in a SpreadsheetML drawing.
+ * Possible shape types are defined in {@link org.apache.poi.ss.usermodel.ShapeTypes}
+ *
+ * @author Yegor Kozlov
+ */
+public class XSSFSimpleShape extends XSSFShape { // TODO - instantiable superclass
+    /**
+     * A default instance of CTShape used for creating new shapes.
+     */
+    private static CTShape prototype = null;
+
+    /**
+     *  Xml bean that stores properties of this shape
+     */
+    private CTShape ctShape;
+
+    protected XSSFSimpleShape(XSSFDrawing drawing, CTShape ctShape) {
+        this.drawing = drawing;
+        this.ctShape = ctShape;
+    }
+
+    /**
+     * Prototype with the default structure of a new auto-shape.
+     */
+    protected static CTShape prototype() {
+        if(prototype == null) {
+            CTShape shape = CTShape.Factory.newInstance();
+
+            CTShapeNonVisual nv = shape.addNewNvSpPr();
+            CTNonVisualDrawingProps nvp = nv.addNewCNvPr();
+            nvp.setId(1);
+            nvp.setName("Shape 1");
+            nv.addNewCNvSpPr();
+
+            CTShapeProperties sp = shape.addNewSpPr();
+            CTTransform2D t2d = sp.addNewXfrm();
+            CTPositiveSize2D p1 = t2d.addNewExt();
+            p1.setCx(0);
+            p1.setCy(0);
+            CTPoint2D p2 = t2d.addNewOff();
+            p2.setX(0);
+            p2.setY(0);
+
+            CTPresetGeometry2D geom = sp.addNewPrstGeom();
+            geom.setPrst(STShapeType.RECT);
+            geom.addNewAvLst();
+
+            CTShapeStyle style = shape.addNewStyle();
+            CTSchemeColor scheme = style.addNewLnRef().addNewSchemeClr();
+            scheme.setVal(STSchemeColorVal.ACCENT_1);
+            scheme.addNewShade().setVal(50000);
+            style.getLnRef().setIdx(2);
+
+            CTStyleMatrixReference fillref = style.addNewFillRef();
+            fillref.setIdx(1);
+            fillref.addNewSchemeClr().setVal(STSchemeColorVal.ACCENT_1);
+
+            CTStyleMatrixReference effectRef = style.addNewEffectRef();
+            effectRef.setIdx(0);
+            effectRef.addNewSchemeClr().setVal(STSchemeColorVal.ACCENT_1);
+
+            CTFontReference fontRef = style.addNewFontRef();
+            fontRef.setIdx(STFontCollectionIndex.MINOR);
+            fontRef.addNewSchemeClr().setVal(STSchemeColorVal.LT_1);
+
+            CTTextBody body = shape.addNewTxBody();
+            CTTextBodyProperties bodypr = body.addNewBodyPr();
+            bodypr.setAnchor(STTextAnchoringType.CTR);
+            bodypr.setRtlCol(false);
+            CTTextParagraph p = body.addNewP();
+            p.addNewPPr().setAlgn(STTextAlignType.CTR);
+            CTTextCharacterProperties endPr = p.addNewEndParaRPr();
+            endPr.setLang("en-US");
+            endPr.setSz(1100);
+
+            body.addNewLstStyle();
+
+            prototype = shape;
+        }
+        return prototype;
+    }
+
+    public CTShape getCTShape(){
+        return ctShape;
+    }
+
+    /**
+     * Gets the shape type, one of the constants defined in {@link org.apache.poi.ss.usermodel.ShapeTypes}.
+     *
+     * @return the shape type
+     * @see org.apache.poi.ss.usermodel.ShapeTypes
+     */
+    public int getShapeType() {
+        return ctShape.getSpPr().getPrstGeom().getPrst().intValue();
+    }
+
+    /**
+     * Sets the shape types.
+     *
+     * @param type the shape type, one of the constants defined in {@link org.apache.poi.ss.usermodel.ShapeTypes}.
+     * @see org.apache.poi.ss.usermodel.ShapeTypes
+     */
+    public void setShapeType(int type) {
+        ctShape.getSpPr().getPrstGeom().setPrst(STShapeType.Enum.forInt(type));
+    }
+
+    protected CTShapeProperties getShapeProperties(){
+        return ctShape.getSpPr();
+    }
+
+    public void setText(XSSFRichTextString str){
+
+        XSSFWorkbook wb = (XSSFWorkbook)getDrawing().getParent().getParent();
+        str.setStylesTableReference(wb.getStylesSource());
+
+        CTTextParagraph p = CTTextParagraph.Factory.newInstance();
+        if(str.numFormattingRuns() == 0){
+            CTRegularTextRun r = p.addNewR();
+            CTTextCharacterProperties rPr = r.addNewRPr();
+            rPr.setLang("en-US");
+            rPr.setSz(1100);
+            r.setT(str.getString());
+
+        } else {
+            for (int i = 0; i < str.getCTRst().sizeOfRArray(); i++) {
+                CTRElt lt = str.getCTRst().getRArray(i);
+                CTRPrElt ltPr = lt.getRPr();
+
+                CTRegularTextRun r = p.addNewR();
+                CTTextCharacterProperties rPr = r.addNewRPr();
+                rPr.setLang("en-US");
+
+                applyAttributes(ltPr, rPr);
+
+                r.setT(lt.getT());
+            }
+        }
+        ctShape.getTxBody().setPArray(new CTTextParagraph[]{p});
+
+    }
+
+    /**
+     *
+     * CTRPrElt --> CTFont adapter
+     */
+    private static void applyAttributes(CTRPrElt pr, CTTextCharacterProperties rPr){
+
+        if(pr.sizeOfBArray() > 0) rPr.setB(pr.getBArray(0).getVal());
+        //if(pr.sizeOfUArray() > 0) rPr.setU(pr.getUArray(0).getVal());
+        if(pr.sizeOfIArray() > 0) rPr.setI(pr.getIArray(0).getVal());
+
+        CTTextFont rFont = rPr.addNewLatin();
+        rFont.setTypeface(pr.sizeOfRFontArray() > 0 ? pr.getRFontArray(0).getVal() : "Arial");
+    }
+}

Modified: poi/trunk/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFTextBox.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFTextBox.java?rev=776607&r1=776606&r2=776607&view=diff
==============================================================================
--- poi/trunk/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFTextBox.java (original)
+++ poi/trunk/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFTextBox.java Wed May 20 08:02:35 2009
@@ -1,32 +1,32 @@
-/* ====================================================================
-   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.
-==================================================================== */
-package org.apache.poi.xssf.usermodel;
-
-import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.*;
-
-/**
- * Represents a text box in a SpreadsheetML drawing.
- *
- * @author Yegor Kozlov
- */
-public class XSSFTextBox extends XSSFSimpleShape {
-
-    protected XSSFTextBox(XSSFDrawing drawing, CTShape ctShape) {
-        super(drawing, ctShape);
-    }
-
-}
+/* ====================================================================
+   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.
+==================================================================== */
+
+package org.apache.poi.xssf.usermodel;
+
+import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.*;
+
+/**
+ * Represents a text box in a SpreadsheetML drawing.
+ *
+ * @author Yegor Kozlov
+ */
+public final class XSSFTextBox extends XSSFSimpleShape {
+
+    protected XSSFTextBox(XSSFDrawing drawing, CTShape ctShape) {
+        super(drawing, ctShape);
+    }
+}

Modified: poi/trunk/src/ooxml/java/org/apache/poi/xssf/usermodel/helpers/XSSFRowShifter.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/ooxml/java/org/apache/poi/xssf/usermodel/helpers/XSSFRowShifter.java?rev=776607&r1=776606&r2=776607&view=diff
==============================================================================
--- poi/trunk/src/ooxml/java/org/apache/poi/xssf/usermodel/helpers/XSSFRowShifter.java (original)
+++ poi/trunk/src/ooxml/java/org/apache/poi/xssf/usermodel/helpers/XSSFRowShifter.java Wed May 20 08:02:35 2009
@@ -1,189 +1,190 @@
-/* ====================================================================
-   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.
-==================================================================== */
-package org.apache.poi.xssf.usermodel.helpers;
-
-import org.apache.poi.xssf.usermodel.*;
-import org.apache.poi.ss.util.CellRangeAddress;
-import org.apache.poi.ss.formula.FormulaParser;
-import org.apache.poi.ss.formula.FormulaType;
-import org.apache.poi.ss.formula.FormulaRenderer;
-import org.apache.poi.ss.usermodel.Row;
-import org.apache.poi.ss.usermodel.Cell;
-import org.apache.poi.hssf.record.formula.FormulaShifter;
-import org.apache.poi.hssf.record.formula.Ptg;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCell;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCellFormula;
-
-import java.util.List;
-import java.util.ArrayList;
-
-/**
- * @author Yegor Kozlov
- */
-public class XSSFRowShifter {
-    private final XSSFSheet sheet;
-
-    public XSSFRowShifter(XSSFSheet sh) {
-        sheet = sh;
-    }
-
-    /**
-     * Shift merged regions
-     *
-     * @param startRow the row to start shifting
-     * @param endRow   the row to end shifting
-     * @param n        the number of rows to shift
-     * @return an array of affected cell regions
-     */
-    public List<CellRangeAddress> shiftMerged(int startRow, int endRow, int n) {
-        List<CellRangeAddress> shiftedRegions = new ArrayList<CellRangeAddress>();
-        //move merged regions completely if they fall within the new region boundaries when they are shifted
-        for (int i = 0; i < sheet.getNumMergedRegions(); i++) {
-            CellRangeAddress merged = sheet.getMergedRegion(i);
-
-            boolean inStart = (merged.getFirstRow() >= startRow || merged.getLastRow() >= startRow);
-            boolean inEnd = (merged.getFirstRow() <= endRow || merged.getLastRow() <= endRow);
-
-            //don't check if it's not within the shifted area
-            if (!inStart || !inEnd) {
-                continue;
-            }
-
-            //only shift if the region outside the shifted rows is not merged too
-            if (!containsCell(merged, startRow - 1, 0) && !containsCell(merged, endRow + 1, 0)) {
-                merged.setFirstRow(merged.getFirstRow() + n);
-                merged.setLastRow(merged.getLastRow() + n);
-                //have to remove/add it back
-                shiftedRegions.add(merged);
-                sheet.removeMergedRegion(i);
-                i = i - 1; // we have to back up now since we removed one
-            }
-        }
-
-        //read so it doesn't get shifted again
-        for (CellRangeAddress region : shiftedRegions) {
-            sheet.addMergedRegion(region);
-        }
-        return shiftedRegions;
-    }
-
-    /**
-     * Check if the  row and column are in the specified cell range
-     *
-     * @param cr    the cell range to check in
-     * @param rowIx the row to check
-     * @param colIx the column to check
-     * @return true if the range contains the cell [rowIx,colIx]
-     */
-    private static boolean containsCell(CellRangeAddress cr, int rowIx, int colIx) {
-        if (cr.getFirstRow() <= rowIx && cr.getLastRow() >= rowIx
-                && cr.getFirstColumn() <= colIx && cr.getLastColumn() >= colIx) {
-            return true;
-        }
-        return false;
-    }
-
-    /**
-     * Updated named ranges
-     */
-    public void updateNamedRanges(FormulaShifter shifter) {
-        XSSFWorkbook wb = sheet.getWorkbook();
-        XSSFEvaluationWorkbook fpb = XSSFEvaluationWorkbook.create(wb);
-        for (int i = 0; i < wb.getNumberOfNames(); i++) {
-            XSSFName name = wb.getNameAt(i);
-            String formula = name.getRefersToFormula();
-            int sheetIndex = name.getSheetIndex();
-
-            Ptg[] ptgs = FormulaParser.parse(formula, fpb, FormulaType.NAMEDRANGE, sheetIndex);
-            if (shifter.adjustFormula(ptgs, sheetIndex)) {
-                String shiftedFmla = FormulaRenderer.toFormulaString(fpb, ptgs);
-                name.setRefersToFormula(shiftedFmla);
-            }
-
-        }
-    }
-
-    /**
-     * Update formulas.
-     */
-    public void updateFormulas(FormulaShifter shifter) {
-        //update formulas on the parent sheet
-        updateSheetFormulas(sheet, shifter);
-
-        //update formulas on other sheets
-        XSSFWorkbook wb = sheet.getWorkbook();
-        for (XSSFSheet sh : wb) {
-            if (sheet == sh) continue;
-            updateSheetFormulas(sh, shifter);
-        }
-    }
-
-    private void updateSheetFormulas(XSSFSheet sh, FormulaShifter shifter) {
-        for (Row r : sh) {
-            XSSFRow row = (XSSFRow) r;
-            updateRowFormulas(row, shifter);
-        }
-    }
-
-    private void updateRowFormulas(XSSFRow row, FormulaShifter shifter) {
-        for (Cell c : row) {
-            XSSFCell cell = (XSSFCell) c;
-
-            CTCell ctCell = cell.getCTCell();
-            if (ctCell.isSetF()) {
-                CTCellFormula f = ctCell.getF();
-                String formula = f.getStringValue();
-                if (formula.length() > 0) {
-                    String shiftedFormula = shiftFormula(row, formula, shifter);
-                    if (shiftedFormula != null) {
-                        f.setStringValue(shiftedFormula);
-                    }
-                }
-
-                if (f.isSetRef()) { //Range of cells which the formula applies to.
-                    String ref = f.getRef();
-                    String shiftedRef = shiftFormula(row, ref, shifter);
-                    if (shiftedRef != null) f.setRef(shiftedRef);
-                }
-            }
-
-        }
-    }
-
-    /**
-     * Shift a formula using the supplied FormulaShifter
-     *
-     * @param row     the row of the cell this formula belongs to. Used to get a reference to the parent workbook.
-     * @param formula the formula to shift
-     * @param shifter the FormulaShifter object that operates on the parsed formula tokens
-     * @return the shifted formula if the formula was changed,
-     *         <code>null</code> if the formula wasn't modified
-     */
-    private static String shiftFormula(XSSFRow row, String formula, FormulaShifter shifter) {
-        XSSFSheet sheet = row.getSheet();
-        XSSFWorkbook wb = sheet.getWorkbook();
-        int sheetIndex = wb.getSheetIndex(sheet);
-        XSSFEvaluationWorkbook fpb = XSSFEvaluationWorkbook.create(wb);
-        Ptg[] ptgs = FormulaParser.parse(formula, fpb, FormulaType.CELL, sheetIndex);
-        String shiftedFmla = null;
-        if (shifter.adjustFormula(ptgs, sheetIndex)) {
-            shiftedFmla = FormulaRenderer.toFormulaString(fpb, ptgs);
-        }
-        return shiftedFmla;
-    }
-
-}
+/* ====================================================================
+   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.
+==================================================================== */
+
+package org.apache.poi.xssf.usermodel.helpers;
+
+import org.apache.poi.xssf.usermodel.*;
+import org.apache.poi.ss.util.CellRangeAddress;
+import org.apache.poi.ss.formula.FormulaParser;
+import org.apache.poi.ss.formula.FormulaType;
+import org.apache.poi.ss.formula.FormulaRenderer;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.hssf.record.formula.FormulaShifter;
+import org.apache.poi.hssf.record.formula.Ptg;
+import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCell;
+import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCellFormula;
+
+import java.util.List;
+import java.util.ArrayList;
+
+/**
+ * @author Yegor Kozlov
+ */
+public final class XSSFRowShifter {
+    private final XSSFSheet sheet;
+
+    public XSSFRowShifter(XSSFSheet sh) {
+        sheet = sh;
+    }
+
+    /**
+     * Shift merged regions
+     *
+     * @param startRow the row to start shifting
+     * @param endRow   the row to end shifting
+     * @param n        the number of rows to shift
+     * @return an array of affected cell regions
+     */
+    public List<CellRangeAddress> shiftMerged(int startRow, int endRow, int n) {
+        List<CellRangeAddress> shiftedRegions = new ArrayList<CellRangeAddress>();
+        //move merged regions completely if they fall within the new region boundaries when they are shifted
+        for (int i = 0; i < sheet.getNumMergedRegions(); i++) {
+            CellRangeAddress merged = sheet.getMergedRegion(i);
+
+            boolean inStart = (merged.getFirstRow() >= startRow || merged.getLastRow() >= startRow);
+            boolean inEnd = (merged.getFirstRow() <= endRow || merged.getLastRow() <= endRow);
+
+            //don't check if it's not within the shifted area
+            if (!inStart || !inEnd) {
+                continue;
+            }
+
+            //only shift if the region outside the shifted rows is not merged too
+            if (!containsCell(merged, startRow - 1, 0) && !containsCell(merged, endRow + 1, 0)) {
+                merged.setFirstRow(merged.getFirstRow() + n);
+                merged.setLastRow(merged.getLastRow() + n);
+                //have to remove/add it back
+                shiftedRegions.add(merged);
+                sheet.removeMergedRegion(i);
+                i = i - 1; // we have to back up now since we removed one
+            }
+        }
+
+        //read so it doesn't get shifted again
+        for (CellRangeAddress region : shiftedRegions) {
+            sheet.addMergedRegion(region);
+        }
+        return shiftedRegions;
+    }
+
+    /**
+     * Check if the  row and column are in the specified cell range
+     *
+     * @param cr    the cell range to check in
+     * @param rowIx the row to check
+     * @param colIx the column to check
+     * @return true if the range contains the cell [rowIx,colIx]
+     */
+    private static boolean containsCell(CellRangeAddress cr, int rowIx, int colIx) {
+        if (cr.getFirstRow() <= rowIx && cr.getLastRow() >= rowIx
+                && cr.getFirstColumn() <= colIx && cr.getLastColumn() >= colIx) {
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Updated named ranges
+     */
+    public void updateNamedRanges(FormulaShifter shifter) {
+        XSSFWorkbook wb = sheet.getWorkbook();
+        XSSFEvaluationWorkbook fpb = XSSFEvaluationWorkbook.create(wb);
+        for (int i = 0; i < wb.getNumberOfNames(); i++) {
+            XSSFName name = wb.getNameAt(i);
+            String formula = name.getRefersToFormula();
+            int sheetIndex = name.getSheetIndex();
+
+            Ptg[] ptgs = FormulaParser.parse(formula, fpb, FormulaType.NAMEDRANGE, sheetIndex);
+            if (shifter.adjustFormula(ptgs, sheetIndex)) {
+                String shiftedFmla = FormulaRenderer.toFormulaString(fpb, ptgs);
+                name.setRefersToFormula(shiftedFmla);
+            }
+
+        }
+    }
+
+    /**
+     * Update formulas.
+     */
+    public void updateFormulas(FormulaShifter shifter) {
+        //update formulas on the parent sheet
+        updateSheetFormulas(sheet, shifter);
+
+        //update formulas on other sheets
+        XSSFWorkbook wb = sheet.getWorkbook();
+        for (XSSFSheet sh : wb) {
+            if (sheet == sh) continue;
+            updateSheetFormulas(sh, shifter);
+        }
+    }
+
+    private void updateSheetFormulas(XSSFSheet sh, FormulaShifter shifter) {
+        for (Row r : sh) {
+            XSSFRow row = (XSSFRow) r;
+            updateRowFormulas(row, shifter);
+        }
+    }
+
+    private void updateRowFormulas(XSSFRow row, FormulaShifter shifter) {
+        for (Cell c : row) {
+            XSSFCell cell = (XSSFCell) c;
+
+            CTCell ctCell = cell.getCTCell();
+            if (ctCell.isSetF()) {
+                CTCellFormula f = ctCell.getF();
+                String formula = f.getStringValue();
+                if (formula.length() > 0) {
+                    String shiftedFormula = shiftFormula(row, formula, shifter);
+                    if (shiftedFormula != null) {
+                        f.setStringValue(shiftedFormula);
+                    }
+                }
+
+                if (f.isSetRef()) { //Range of cells which the formula applies to.
+                    String ref = f.getRef();
+                    String shiftedRef = shiftFormula(row, ref, shifter);
+                    if (shiftedRef != null) f.setRef(shiftedRef);
+                }
+            }
+
+        }
+    }
+
+    /**
+     * Shift a formula using the supplied FormulaShifter
+     *
+     * @param row     the row of the cell this formula belongs to. Used to get a reference to the parent workbook.
+     * @param formula the formula to shift
+     * @param shifter the FormulaShifter object that operates on the parsed formula tokens
+     * @return the shifted formula if the formula was changed,
+     *         <code>null</code> if the formula wasn't modified
+     */
+    private static String shiftFormula(XSSFRow row, String formula, FormulaShifter shifter) {
+        XSSFSheet sheet = row.getSheet();
+        XSSFWorkbook wb = sheet.getWorkbook();
+        int sheetIndex = wb.getSheetIndex(sheet);
+        XSSFEvaluationWorkbook fpb = XSSFEvaluationWorkbook.create(wb);
+        Ptg[] ptgs = FormulaParser.parse(formula, fpb, FormulaType.CELL, sheetIndex);
+        String shiftedFmla = null;
+        if (shifter.adjustFormula(ptgs, sheetIndex)) {
+            shiftedFmla = FormulaRenderer.toFormulaString(fpb, ptgs);
+        }
+        return shiftedFmla;
+    }
+
+}



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@poi.apache.org
For additional commands, e-mail: commits-help@poi.apache.org