diff --git a/src/examples/src/org/apache/poi/xslf/usermodel/Tutorial4.java b/src/examples/src/org/apache/poi/xslf/usermodel/Tutorial4.java
index 0742cddea..ecfc98667 100644
--- a/src/examples/src/org/apache/poi/xslf/usermodel/Tutorial4.java
+++ b/src/examples/src/org/apache/poi/xslf/usermodel/Tutorial4.java
@@ -20,7 +20,7 @@
package org.apache.poi.xslf.usermodel;
import java.awt.Color;
-import java.awt.geom.Rectangle2D;
+import java.awt.Rectangle;
import java.io.FileOutputStream;
import java.io.IOException;
@@ -40,7 +40,7 @@ public class Tutorial4 {
XSLFSlide slide = ppt.createSlide();
XSLFTable tbl = slide.createTable();
- tbl.setAnchor(new Rectangle2D.Double(50, 50, 450, 300));
+ tbl.setAnchor(new Rectangle(50, 50, 450, 300));
int numColumns = 3;
int numRows = 5;
diff --git a/src/integrationtest/org/apache/poi/stress/SlideShowHandler.java b/src/integrationtest/org/apache/poi/stress/SlideShowHandler.java
index 34830f1e0..9d6d1b3dc 100644
--- a/src/integrationtest/org/apache/poi/stress/SlideShowHandler.java
+++ b/src/integrationtest/org/apache/poi/stress/SlideShowHandler.java
@@ -29,14 +29,13 @@ import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
-import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
-import org.apache.poi.sl.SlideShowFactory;
import org.apache.poi.sl.draw.Drawable;
import org.apache.poi.sl.usermodel.PictureData;
import org.apache.poi.sl.usermodel.Shape;
import org.apache.poi.sl.usermodel.ShapeContainer;
import org.apache.poi.sl.usermodel.Slide;
import org.apache.poi.sl.usermodel.SlideShow;
+import org.apache.poi.sl.usermodel.SlideShowFactory;
import org.apache.poi.sl.usermodel.TextParagraph;
import org.apache.poi.sl.usermodel.TextRun;
import org.apache.poi.sl.usermodel.TextShape;
@@ -55,12 +54,7 @@ public abstract class SlideShowHandler extends POIFSFileHandler {
readContent(ss);
// read in the writen file
- SlideShow,?> read;
- try {
- read = SlideShowFactory.create(new ByteArrayInputStream(out.toByteArray()));
- } catch (InvalidFormatException e) {
- throw new IllegalStateException(e);
- }
+ SlideShow,?> read = SlideShowFactory.create(new ByteArrayInputStream(out.toByteArray()));
assertNotNull(read);
readContent(read);
diff --git a/src/java/org/apache/poi/sl/draw/DrawBackground.java b/src/java/org/apache/poi/sl/draw/DrawBackground.java
index 4072fe4bc..a06c2da23 100644
--- a/src/java/org/apache/poi/sl/draw/DrawBackground.java
+++ b/src/java/org/apache/poi/sl/draw/DrawBackground.java
@@ -20,6 +20,7 @@ package org.apache.poi.sl.draw;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Paint;
+import java.awt.Rectangle;
import java.awt.geom.Rectangle2D;
import org.apache.poi.sl.usermodel.Background;
@@ -35,12 +36,12 @@ public class DrawBackground extends DrawShape {
@SuppressWarnings("rawtypes")
public void draw(Graphics2D graphics) {
Dimension pg = shape.getSheet().getSlideShow().getPageSize();
- final Rectangle2D anchor = new Rectangle2D.Double(0, 0, pg.getWidth(), pg.getHeight());
+ final Rectangle anchor = new Rectangle(0, 0, (int)pg.getWidth(), (int)pg.getHeight());
PlaceableShape,?> ps = new PlaceableShape(){
public ShapeContainer,?> getParent() { return null; }
- public Rectangle2D getAnchor() { return anchor; }
- public void setAnchor(Rectangle2D anchor) {}
+ public Rectangle getAnchor() { return anchor; }
+ public void setAnchor(Rectangle newAnchor) {}
public double getRotation() { return 0; }
public void setRotation(double theta) {}
public void setFlipHorizontal(boolean flip) {}
diff --git a/src/java/org/apache/poi/sl/draw/DrawPictureShape.java b/src/java/org/apache/poi/sl/draw/DrawPictureShape.java
index 43586f111..534d246ad 100644
--- a/src/java/org/apache/poi/sl/draw/DrawPictureShape.java
+++ b/src/java/org/apache/poi/sl/draw/DrawPictureShape.java
@@ -17,13 +17,16 @@
package org.apache.poi.sl.draw;
+import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Insets;
+import java.awt.Rectangle;
import java.awt.geom.Rectangle2D;
import java.io.IOException;
import org.apache.poi.sl.usermodel.PictureData;
import org.apache.poi.sl.usermodel.PictureShape;
+import org.apache.poi.sl.usermodel.RectAlign;
public class DrawPictureShape extends DrawSimpleShape {
@@ -56,4 +59,117 @@ public class DrawPictureShape extends DrawSimpleShape {
protected PictureShape,?> getShape() {
return (PictureShape,?>)shape;
}
+
+ /**
+ * Resize this picture to the default size.
+ *
+ * For PNG and JPEG resizes the image to 100%,
+ * for other types, if the size can't be determined it will be 200x200 pixels.
+ */
+ public void resize() {
+ PictureShape,?> ps = getShape();
+ Dimension dim = ps.getPictureData().getImageDimension();
+
+ Rectangle origRect = ps.getAnchor();
+ int x = (int)origRect.getX();
+ int y = (int)origRect.getY();
+ int w = (int)dim.getWidth();
+ int h = (int)dim.getHeight();
+ ps.setAnchor(new Rectangle(x, y, w, h));
+ }
+
+
+ /**
+ * Fit picture shape into the target rectangle, maintaining the aspect ratio
+ * and repositioning within the target rectangle with a centered alignment.
+ *
+ * @param target The target rectangle
+ */
+ public void resize(Rectangle target) {
+ resize(target, RectAlign.CENTER);
+ }
+
+
+ /**
+ * Fit picture shape into the target rectangle, maintaining the aspect ratio
+ * and repositioning within the target rectangle based on the specified
+ * alignment (gravity).
+ *
+ * @param target The target rectangle
+ * @param align
+ * The alignment within the target rectangle when resizing.
+ * A null value corresponds to RectAlign.CENTER
+ */
+ public void resize(Rectangle target, RectAlign align) {
+ PictureShape,?> ps = getShape();
+ Dimension dim = ps.getPictureData().getImageDimension();
+ if (dim.width <= 0 || dim.height <= 0) {
+ // nothing useful to be done for this case
+ ps.setAnchor(target);
+ return;
+ }
+
+ double w = target.getWidth();
+ double h = target.getHeight();
+
+ // scaling
+ double sx = w / dim.width;
+ double sy = h / dim.height;
+
+ // position adjustments
+ double dx = 0, dy = 0;
+
+ if (sx > sy) {
+ // use y-scaling for both, reposition x accordingly
+ w = sy * dim.width;
+ dx = target.getWidth() - w;
+ } else if (sy > sx) {
+ // use x-scaling for both, reposition y accordingly
+ h = sx * dim.height;
+ dy = target.getHeight() - h;
+ } else {
+ // uniform scaling, can use target values directly
+ ps.setAnchor(target);
+ return;
+ }
+
+ // the positioning
+ double x = target.getX();
+ double y = target.getY();
+ switch (align) {
+ case TOP: // X=balance, Y=ok
+ x += dx/2;
+ break;
+ case TOP_RIGHT: // X=shift, Y=ok
+ x += dx;
+ break;
+ case RIGHT: // X=shift, Y=balance
+ x += dx;
+ y += dy/2;
+ break;
+ case BOTTOM_RIGHT: // X=shift, Y=shift
+ x += dx;
+ y += dy;
+ break;
+ case BOTTOM: // X=balance, Y=shift
+ x += dx/2;
+ y += dy;
+ break;
+ case BOTTOM_LEFT: // X=ok, Y=shift
+ y += dy;
+ break;
+ case LEFT: // X=ok, Y=balance
+ y += dy/2;
+ break;
+ case TOP_LEFT: // X=ok, Y=ok
+ /* no-op */
+ break;
+ default: // CENTER: X=balance, Y=balance
+ x += dx/2;
+ y += dy/2;
+ break;
+ }
+
+ ps.setAnchor(new Rectangle((int)x, (int)y, (int)w, (int)h));
+ }
}
diff --git a/src/java/org/apache/poi/sl/draw/DrawSimpleShape.java b/src/java/org/apache/poi/sl/draw/DrawSimpleShape.java
index 37cd6d8b8..941e5c72d 100644
--- a/src/java/org/apache/poi/sl/draw/DrawSimpleShape.java
+++ b/src/java/org/apache/poi/sl/draw/DrawSimpleShape.java
@@ -25,10 +25,8 @@ import java.awt.geom.AffineTransform;
import java.awt.geom.Ellipse2D;
import java.awt.geom.GeneralPath;
import java.awt.geom.Rectangle2D;
+import java.io.IOException;
import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.Reader;
-import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
@@ -145,7 +143,7 @@ public class DrawSimpleShape extends DrawShape {
double alpha = Math.atan(anchor.getHeight() / anchor.getWidth());
AffineTransform at = new AffineTransform();
- java.awt.Shape shape = null;
+ java.awt.Shape tailShape = null;
Path p = null;
Rectangle2D bounds;
final double scaleY = Math.pow(2, tailWidth.ordinal()+1);
@@ -153,8 +151,8 @@ public class DrawSimpleShape extends DrawShape {
switch (deco.getTailShape()) {
case OVAL:
p = new Path();
- shape = new Ellipse2D.Double(0, 0, lineWidth * scaleX, lineWidth * scaleY);
- bounds = shape.getBounds2D();
+ tailShape = new Ellipse2D.Double(0, 0, lineWidth * scaleX, lineWidth * scaleY);
+ bounds = tailShape.getBounds2D();
at.translate(x2 - bounds.getWidth() / 2, y2 - bounds.getHeight() / 2);
at.rotate(alpha, bounds.getX() + bounds.getWidth() / 2, bounds.getY() + bounds.getHeight() / 2);
break;
@@ -165,7 +163,7 @@ public class DrawSimpleShape extends DrawShape {
arrow.moveTo((float) (-lineWidth * scaleX), (float) (-lineWidth * scaleY / 2));
arrow.lineTo(0, 0);
arrow.lineTo((float) (-lineWidth * scaleX), (float) (lineWidth * scaleY / 2));
- shape = arrow;
+ tailShape = arrow;
at.translate(x2, y2);
at.rotate(alpha);
break;
@@ -176,7 +174,7 @@ public class DrawSimpleShape extends DrawShape {
triangle.lineTo(0, 0);
triangle.lineTo((float) (-lineWidth * scaleX), (float) (lineWidth * scaleY / 2));
triangle.closePath();
- shape = triangle;
+ tailShape = triangle;
at.translate(x2, y2);
at.rotate(alpha);
break;
@@ -184,10 +182,10 @@ public class DrawSimpleShape extends DrawShape {
break;
}
- if (shape != null) {
- shape = at.createTransformedShape(shape);
+ if (tailShape != null) {
+ tailShape = at.createTransformedShape(tailShape);
}
- return shape == null ? null : new Outline(shape, p);
+ return tailShape == null ? null : new Outline(tailShape, p);
}
protected Outline getHeadDecoration(Graphics2D graphics, LineDecoration deco, BasicStroke stroke) {
@@ -203,7 +201,7 @@ public class DrawSimpleShape extends DrawShape {
double alpha = Math.atan(anchor.getHeight() / anchor.getWidth());
AffineTransform at = new AffineTransform();
- java.awt.Shape shape = null;
+ java.awt.Shape headShape = null;
Path p = null;
Rectangle2D bounds;
final double scaleY = Math.pow(2, headWidth.ordinal()+1);
@@ -211,8 +209,8 @@ public class DrawSimpleShape extends DrawShape {
switch (deco.getHeadShape()) {
case OVAL:
p = new Path();
- shape = new Ellipse2D.Double(0, 0, lineWidth * scaleX, lineWidth * scaleY);
- bounds = shape.getBounds2D();
+ headShape = new Ellipse2D.Double(0, 0, lineWidth * scaleX, lineWidth * scaleY);
+ bounds = headShape.getBounds2D();
at.translate(x1 - bounds.getWidth() / 2, y1 - bounds.getHeight() / 2);
at.rotate(alpha, bounds.getX() + bounds.getWidth() / 2, bounds.getY() + bounds.getHeight() / 2);
break;
@@ -223,7 +221,7 @@ public class DrawSimpleShape extends DrawShape {
arrow.moveTo((float) (lineWidth * scaleX), (float) (-lineWidth * scaleY / 2));
arrow.lineTo(0, 0);
arrow.lineTo((float) (lineWidth * scaleX), (float) (lineWidth * scaleY / 2));
- shape = arrow;
+ headShape = arrow;
at.translate(x1, y1);
at.rotate(alpha);
break;
@@ -234,7 +232,7 @@ public class DrawSimpleShape extends DrawShape {
triangle.lineTo(0, 0);
triangle.lineTo((float) (lineWidth * scaleX), (float) (lineWidth * scaleY / 2));
triangle.closePath();
- shape = triangle;
+ headShape = triangle;
at.translate(x1, y1);
at.rotate(alpha);
break;
@@ -242,10 +240,10 @@ public class DrawSimpleShape extends DrawShape {
break;
}
- if (shape != null) {
- shape = at.createTransformedShape(shape);
+ if (headShape != null) {
+ headShape = at.createTransformedShape(headShape);
}
- return shape == null ? null : new Outline(shape, p);
+ return headShape == null ? null : new Outline(headShape, p);
}
public BasicStroke getStroke() {
@@ -296,7 +294,7 @@ public class DrawSimpleShape extends DrawShape {
, Paint fill
, Paint line
) {
- Shadow shadow = getShape().getShadow();
+ Shadow,?> shadow = getShape().getShadow();
if (shadow == null || (fill == null && line == null)) return;
SolidPaint shadowPaint = shadow.getFillStyle();
@@ -347,7 +345,6 @@ public class DrawSimpleShape extends DrawShape {
String packageName = "org.apache.poi.sl.draw.binding";
InputStream presetIS = Drawable.class.getResourceAsStream("presetShapeDefinitions.xml");
- Reader xml = new InputStreamReader( presetIS, Charset.forName("UTF-8") );
// StAX:
EventFilter startElementFilter = new EventFilter() {
@@ -359,7 +356,7 @@ public class DrawSimpleShape extends DrawShape {
try {
XMLInputFactory staxFactory = XMLInputFactory.newInstance();
- XMLEventReader staxReader = staxFactory.createXMLEventReader(xml);
+ XMLEventReader staxReader = staxFactory.createXMLEventReader(presetIS);
XMLEventReader staxFiltRd = staxFactory.createFilteredReader(staxReader, startElementFilter);
// Ignore StartElement:
staxFiltRd.nextEvent();
@@ -378,6 +375,12 @@ public class DrawSimpleShape extends DrawShape {
}
} catch (Exception e) {
throw new RuntimeException("Unable to load preset geometries.", e);
+ } finally {
+ try {
+ presetIS.close();
+ } catch (IOException e) {
+ throw new RuntimeException("Unable to load preset geometries.", e);
+ }
}
}
diff --git a/src/java/org/apache/poi/sl/draw/DrawTextParagraph.java b/src/java/org/apache/poi/sl/draw/DrawTextParagraph.java
index 8cfa48162..735205ec4 100644
--- a/src/java/org/apache/poi/sl/draw/DrawTextParagraph.java
+++ b/src/java/org/apache/poi/sl/draw/DrawTextParagraph.java
@@ -19,6 +19,7 @@ package org.apache.poi.sl.draw;
import java.awt.Graphics2D;
import java.awt.Paint;
+import java.awt.Rectangle;
import java.awt.font.FontRenderContext;
import java.awt.font.LineBreakMeasurer;
import java.awt.font.TextAttribute;
@@ -416,8 +417,8 @@ public class DrawTextParagraph implements Drawable {
private PlaceableShape,?> getParagraphShape() {
PlaceableShape,?> ps = new PlaceableShape(){
public ShapeContainer,?> getParent() { return null; }
- public Rectangle2D getAnchor() { return paragraph.getParentShape().getAnchor(); }
- public void setAnchor(Rectangle2D anchor) {}
+ public Rectangle getAnchor() { return paragraph.getParentShape().getAnchor(); }
+ public void setAnchor(Rectangle anchor) {}
public double getRotation() { return 0; }
public void setRotation(double theta) {}
public void setFlipHorizontal(boolean flip) {}
diff --git a/src/java/org/apache/poi/sl/usermodel/GroupShape.java b/src/java/org/apache/poi/sl/usermodel/GroupShape.java
index a7545a4d4..87396b587 100644
--- a/src/java/org/apache/poi/sl/usermodel/GroupShape.java
+++ b/src/java/org/apache/poi/sl/usermodel/GroupShape.java
@@ -17,7 +17,7 @@
package org.apache.poi.sl.usermodel;
-import java.awt.geom.Rectangle2D;
+import java.awt.Rectangle;
public interface GroupShape<
S extends Shape,
@@ -30,7 +30,7 @@ public interface GroupShape<
*
* @return the coordinate space of this group
*/
- Rectangle2D getInteriorAnchor();
+ Rectangle getInteriorAnchor();
/**
* Sets the coordinate space of this group. All children are constrained
@@ -38,5 +38,5 @@ public interface GroupShape<
*
* @param anchor the coordinate space of this group
*/
- void setInteriorAnchor(Rectangle2D anchor);
+ void setInteriorAnchor(Rectangle anchor);
}
diff --git a/src/java/org/apache/poi/sl/usermodel/PictureData.java b/src/java/org/apache/poi/sl/usermodel/PictureData.java
index 62780773e..60e6266b7 100644
--- a/src/java/org/apache/poi/sl/usermodel/PictureData.java
+++ b/src/java/org/apache/poi/sl/usermodel/PictureData.java
@@ -106,10 +106,16 @@ public interface PictureData {
byte[] getChecksum();
/**
- * Return the original image dimensions
+ * Return the original image dimensions in points
* (for formats supported by BufferedImage).
*
- * Will return a Dimension with zero width/height if the format unsupported.
+ * Will return a Dimension with a default width of 200x200 if the format unsupported.
*/
Dimension getImageDimension();
+
+ /**
+ * Return the original image dimensions in pixels
+ * @see PictureData#getImageDimension()
+ */
+ Dimension getImageDimensionInPixels();
}
\ No newline at end of file
diff --git a/src/java/org/apache/poi/sl/usermodel/PlaceableShape.java b/src/java/org/apache/poi/sl/usermodel/PlaceableShape.java
index 191bad65f..bcba7401c 100644
--- a/src/java/org/apache/poi/sl/usermodel/PlaceableShape.java
+++ b/src/java/org/apache/poi/sl/usermodel/PlaceableShape.java
@@ -17,7 +17,7 @@
package org.apache.poi.sl.usermodel;
-import java.awt.geom.Rectangle2D;
+import java.awt.Rectangle;
public interface PlaceableShape<
S extends Shape,
@@ -29,13 +29,13 @@ public interface PlaceableShape<
* @return the position of this shape within the drawing canvas.
* The coordinates are expressed in points
*/
- Rectangle2D getAnchor();
+ Rectangle getAnchor();
/**
* @param anchor the position of this shape within the drawing canvas.
* The coordinates are expressed in points
*/
- void setAnchor(Rectangle2D anchor);
+ void setAnchor(Rectangle anchor);
/**
* Rotation angle in degrees
diff --git a/src/java/org/apache/poi/sl/usermodel/RectAlign.java b/src/java/org/apache/poi/sl/usermodel/RectAlign.java
new file mode 100644
index 000000000..9ca8d87e2
--- /dev/null
+++ b/src/java/org/apache/poi/sl/usermodel/RectAlign.java
@@ -0,0 +1,74 @@
+/*
+ * ====================================================================
+ * 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.sl.usermodel;
+
+/**
+ * Specifies possible rectangle alignment types.
+ *
+ * @see {@link org.openxmlformats.schemas.drawingml.x2006.main.STRectAlignment}
+ * @see {@link org.apache.poi.sl.draw.binding.STRectAlignment}
+ */
+public enum RectAlign {
+ /** Top-Left rectangle alignment */
+ TOP_LEFT("tl"),
+
+ /** Top rectangle alignment */
+ TOP("t"),
+
+ /** Top-Right rectangle alignment */
+ TOP_RIGHT("tr"),
+
+ /** Left rectangle alignment */
+ LEFT("l"),
+
+ /** Center rectangle alignment */
+ CENTER("ctr"),
+
+ /** Right rectangle alignment */
+ RIGHT("r"),
+
+ /** Bottom-Left rectangle alignment */
+ BOTTOM_LEFT("bl"),
+
+ /** Bottom rectangle alignment */
+ BOTTOM("b"),
+
+ /** Bottom-Right rectangle alignment */
+ BOTTOM_RIGHT("br");
+
+ /** The corresponding xml enum value */
+ private final String dir;
+
+ private RectAlign(String dir) {
+ this.dir = dir;
+ }
+
+
+ /**
+ * The string representation,
+ * which corresponds to the internal XML enum value
+ */
+ @Override
+ public String toString() {
+ return dir;
+ }
+
+}
+
+/* ************************************************************************** */
diff --git a/src/java/org/apache/poi/sl/usermodel/Shadow.java b/src/java/org/apache/poi/sl/usermodel/Shadow.java
index 430dbe384..9afc4e64e 100644
--- a/src/java/org/apache/poi/sl/usermodel/Shadow.java
+++ b/src/java/org/apache/poi/sl/usermodel/Shadow.java
@@ -21,8 +21,11 @@ import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint;
-public interface Shadow {
- SimpleShape getShadowParent();
+public interface Shadow<
+S extends Shape,
+P extends TextParagraph
+> {
+ SimpleShape getShadowParent();
/**
* @return the offset of this shadow in points
diff --git a/src/java/org/apache/poi/sl/usermodel/Shape.java b/src/java/org/apache/poi/sl/usermodel/Shape.java
index 13996fa6c..a05e3bf45 100644
--- a/src/java/org/apache/poi/sl/usermodel/Shape.java
+++ b/src/java/org/apache/poi/sl/usermodel/Shape.java
@@ -17,6 +17,7 @@
package org.apache.poi.sl.usermodel;
+import java.awt.Rectangle;
public interface Shape<
S extends Shape,
@@ -29,4 +30,12 @@ public interface Shape<
* @return the sheet this shape belongs to
*/
Sheet getSheet();
+
+ /**
+ * Returns the anchor (the bounding box rectangle) of this shape.
+ * All coordinates are expressed in points (72 dpi).
+ *
+ * @return the anchor of this shape
+ */
+ Rectangle getAnchor();
}
diff --git a/src/java/org/apache/poi/sl/usermodel/SimpleShape.java b/src/java/org/apache/poi/sl/usermodel/SimpleShape.java
index 95f4590eb..ceed729e0 100644
--- a/src/java/org/apache/poi/sl/usermodel/SimpleShape.java
+++ b/src/java/org/apache/poi/sl/usermodel/SimpleShape.java
@@ -35,5 +35,5 @@ public interface SimpleShape<
boolean isPlaceholder();
- Shadow getShadow();
+ Shadow getShadow();
}
diff --git a/src/java/org/apache/poi/sl/usermodel/SlideShowFactory.java b/src/java/org/apache/poi/sl/usermodel/SlideShowFactory.java
new file mode 100644
index 000000000..9e705dffc
--- /dev/null
+++ b/src/java/org/apache/poi/sl/usermodel/SlideShowFactory.java
@@ -0,0 +1,315 @@
+/* ====================================================================
+ 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.sl.usermodel;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PushbackInputStream;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.security.GeneralSecurityException;
+
+import org.apache.poi.EncryptedDocumentException;
+import org.apache.poi.hssf.record.crypto.Biff8EncryptionKey;
+import org.apache.poi.poifs.crypt.Decryptor;
+import org.apache.poi.poifs.crypt.EncryptionInfo;
+import org.apache.poi.poifs.filesystem.DirectoryNode;
+import org.apache.poi.poifs.filesystem.NPOIFSFileSystem;
+import org.apache.poi.poifs.filesystem.OfficeXmlFileException;
+import org.apache.poi.util.IOUtils;
+
+public class SlideShowFactory {
+ /** The first 4 bytes of an OOXML file, used in detection */
+ private static final byte[] OOXML_FILE_HEADER = { 0x50, 0x4b, 0x03, 0x04 };
+
+ /**
+ * Creates a SlideShow from the given NPOIFSFileSystem.
+ *
+ * @param fs The {@link NPOIFSFileSystem} to read the document from
+ *
+ * @return The created SlideShow
+ *
+ * @throws IOException if an error occurs while reading the data
+ */
+ public static SlideShow,?> create(NPOIFSFileSystem fs) throws IOException {
+ return create(fs, null);
+ }
+
+ /**
+ * Creates a SlideShow from the given NPOIFSFileSystem, which may
+ * be password protected
+ *
+ * @param fs The {@link NPOIFSFileSystem} to read the document from
+ * @param password The password that should be used or null if no password is necessary.
+ *
+ * @return The created SlideShow
+ *
+ * @throws IOException if an error occurs while reading the data
+ */
+ public static SlideShow,?> create(NPOIFSFileSystem fs, String password) throws IOException {
+ DirectoryNode root = fs.getRoot();
+
+ // Encrypted OOXML files go inside OLE2 containers, is this one?
+ if (root.hasEntry(Decryptor.DEFAULT_POIFS_ENTRY)) {
+ EncryptionInfo info = new EncryptionInfo(fs);
+ Decryptor d = Decryptor.getInstance(info);
+
+ boolean passwordCorrect = false;
+ InputStream stream = null;
+ try {
+ if (password != null && d.verifyPassword(password)) {
+ passwordCorrect = true;
+ }
+ if (!passwordCorrect && d.verifyPassword(Decryptor.DEFAULT_PASSWORD)) {
+ passwordCorrect = true;
+ }
+ if (passwordCorrect) {
+ stream = d.getDataStream(root);
+ }
+
+ if (!passwordCorrect) {
+ String err = (password != null)
+ ? "Password incorrect"
+ : "The supplied spreadsheet is protected, but no password was supplied";
+ throw new EncryptedDocumentException(err);
+ }
+
+ return createXSLFSlideShow(stream);
+ } catch (GeneralSecurityException e) {
+ throw new IOException(e);
+ } finally {
+ if (stream != null) stream.close();
+ }
+ }
+
+ // If we get here, it isn't an encrypted PPTX file
+ // So, treat it as a regular HSLF PPT one
+ if (password != null) {
+ Biff8EncryptionKey.setCurrentUserPassword(password);
+ }
+ try {
+ return createHSLFSlideShow(fs);
+ } finally {
+ Biff8EncryptionKey.setCurrentUserPassword(null);
+ }
+ }
+
+ /**
+ * Creates the appropriate HSLFSlideShow / XMLSlideShow from
+ * the given InputStream.
+ *
+ *
Your input stream MUST either support mark/reset, or + * be wrapped as a {@link PushbackInputStream}! Note that + * using an {@link InputStream} has a higher memory footprint + * than using a {@link File}.
+ * + *Note that in order to properly release resources the + * SlideShow should be closed after use. Note also that loading + * from an InputStream requires more memory than loading + * from a File, so prefer {@link #create(File)} where possible. + * + * @param inp The {@link InputStream} to read data from. + * + * @return The created SlideShow + * + * @throws IOException if an error occurs while reading the data + * @throws EncryptedDocumentException If the SlideShow given is password protected + */ + public static SlideShow,?> create(InputStream inp) throws IOException, EncryptedDocumentException { + return create(inp, null); + } + + /** + * Creates the appropriate HSLFSlideShow / XMLSlideShow from + * the given InputStream, which may be password protected. + *
Your input stream MUST either support mark/reset, or + * be wrapped as a {@link PushbackInputStream}! Note that + * using an {@link InputStream} has a higher memory footprint + * than using a {@link File}.
+ * + *Note that in order to properly release resources the + * SlideShow should be closed after use. Note also that loading + * from an InputStream requires more memory than loading + * from a File, so prefer {@link #create(File)} where possible.
+ * + * @param inp The {@link InputStream} to read data from. + * @param password The password that should be used or null if no password is necessary. + * + * @return The created SlideShow + * + * @throws IOException if an error occurs while reading the data + * @throws EncryptedDocumentException If the wrong password is given for a protected file + */ + @SuppressWarnings("resource") + public static SlideShow,?> create(InputStream inp, String password) throws IOException, EncryptedDocumentException { + // If clearly doesn't do mark/reset, wrap up + if (! inp.markSupported()) { + inp = new PushbackInputStream(inp, 8); + } + + // Ensure that there is at least some data there + byte[] header8 = IOUtils.peekFirst8Bytes(inp); + + // Try to create + if (NPOIFSFileSystem.hasPOIFSHeader(header8)) { + NPOIFSFileSystem fs = new NPOIFSFileSystem(inp); + return create(fs, password); + } + if (hasOOXMLHeader(inp)) { + return createXSLFSlideShow(inp); + } + throw new IllegalArgumentException("Your InputStream was neither an OLE2 stream, nor an OOXML stream"); + } + + /** + * Creates the appropriate HSLFSlideShow / XMLSlideShow from + * the given File, which must exist and be readable. + *Note that in order to properly release resources the + * SlideShow should be closed after use. + * + * @param file The file to read data from. + * + * @return The created SlideShow + * + * @throws IOException if an error occurs while reading the data + * @throws EncryptedDocumentException If the SlideShow given is password protected + */ + public static SlideShow,?> create(File file) throws IOException, EncryptedDocumentException { + return create(file, null); + } + + /** + * Creates the appropriate HSLFSlideShow / XMLSlideShow from + * the given File, which must exist and be readable, and + * may be password protected + *
Note that in order to properly release resources the + * SlideShow should be closed after use. + * + * @param file The file to read data from. + * @param password The password that should be used or null if no password is necessary. + * + * @return The created SlideShow + * + * @throws IOException if an error occurs while reading the data + * @throws EncryptedDocumentException If the wrong password is given for a protected file + */ + public static SlideShow,?> create(File file, String password) throws IOException, EncryptedDocumentException { + return create(file, password, false); + } + + /** + * Creates the appropriate HSLFSlideShow / XMLSlideShow from + * the given File, which must exist and be readable, and + * may be password protected + *
Note that in order to properly release resources the
+ * SlideShow should be closed after use.
+ *
+ * @param file The file to read data from.
+ * @param password The password that should be used or null if no password is necessary.
+ * @param readOnly If the SlideShow should be opened in read-only mode to avoid writing back
+ * changes when the document is closed.
+ *
+ * @return The created SlideShow
+ *
+ * @throws IOException if an error occurs while reading the data
+ * @throws EncryptedDocumentException If the wrong password is given for a protected file
+ */
+ @SuppressWarnings("resource")
+ public static SlideShow,?> create(File file, String password, boolean readOnly) throws IOException, EncryptedDocumentException {
+ if (!file.exists()) {
+ throw new FileNotFoundException(file.toString());
+ }
+
+ try {
+ NPOIFSFileSystem fs = new NPOIFSFileSystem(file, readOnly);
+ return create(fs, password);
+ } catch(OfficeXmlFileException e) {
+ return createXSLFSlideShow(file, readOnly);
+ }
+ }
+
+ protected static SlideShow,?> createHSLFSlideShow(Object... args) throws IOException, EncryptedDocumentException {
+ return createSlideShow("org.apache.poi.hslf.usermodel.HSLFSlideShowFactory", args);
+ }
+
+ protected static SlideShow,?> createXSLFSlideShow(Object... args) throws IOException, EncryptedDocumentException {
+ return createSlideShow("org.apache.poi.xslf.usermodel.XSLFSlideShowFactory", args);
+ }
+
+ protected static SlideShow,?> createSlideShow(String factoryClass, Object args[]) throws IOException, EncryptedDocumentException {
+ try {
+ Class> clazz = Thread.currentThread().getContextClassLoader().loadClass(factoryClass);
+ Class> argsClz[] = new Class>[args.length];
+ int i=0;
+ for (Object o : args) {
+ Class> c = o.getClass();
+ if (Boolean.class.isAssignableFrom(c)) {
+ c = boolean.class;
+ } else if (InputStream.class.isAssignableFrom(c)) {
+ c = InputStream.class;
+ }
+ argsClz[i++] = c;
+ }
+ Method m = clazz.getMethod("createSlideShow", argsClz);
+ return (SlideShow,?>)m.invoke(null, args);
+ } catch (InvocationTargetException e) {
+ Throwable t = e.getCause();
+ if (t instanceof IOException) {
+ throw (IOException)t;
+ } else if (t instanceof EncryptedDocumentException) {
+ throw (EncryptedDocumentException)t;
+ } else {
+ throw new IOException(t);
+ }
+ } catch (Exception e) {
+ throw new IOException(e);
+ }
+ }
+
+ /**
+ * This copied over from ooxml, because we can't rely on these classes in the main package
+ *
+ * @see org.apache.poi.POIXMLDocument#hasOOXMLHeader(InputStream)
+ */
+ protected static boolean hasOOXMLHeader(InputStream inp) throws IOException {
+ // We want to peek at the first 4 bytes
+ inp.mark(4);
+
+ byte[] header = new byte[4];
+ int bytesRead = IOUtils.readFully(inp, header);
+
+ // Wind back those 4 bytes
+ if(inp instanceof PushbackInputStream) {
+ PushbackInputStream pin = (PushbackInputStream)inp;
+ pin.unread(header, 0, bytesRead);
+ } else {
+ inp.reset();
+ }
+
+ // Did it match the ooxml zip signature?
+ return (
+ bytesRead == 4 &&
+ header[0] == OOXML_FILE_HEADER[0] &&
+ header[1] == OOXML_FILE_HEADER[1] &&
+ header[2] == OOXML_FILE_HEADER[2] &&
+ header[3] == OOXML_FILE_HEADER[3]
+ );
+ }
+
+}
diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFBackground.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFBackground.java
index 6dbdf2d4f..817d2edcc 100644
--- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFBackground.java
+++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFBackground.java
@@ -19,7 +19,7 @@ package org.apache.poi.xslf.usermodel;
import java.awt.Color;
import java.awt.Dimension;
-import java.awt.geom.Rectangle2D;
+import java.awt.Rectangle;
import org.apache.poi.sl.draw.DrawPaint;
import org.apache.poi.sl.usermodel.Background;
@@ -43,9 +43,9 @@ public class XSLFBackground extends XSLFSimpleShape
}
@Override
- public Rectangle2D getAnchor(){
+ public Rectangle getAnchor(){
Dimension pg = getSheet().getSlideShow().getPageSize();
- return new Rectangle2D.Double(0, 0, pg.getWidth(), pg.getHeight());
+ return new Rectangle(0, 0, (int)pg.getWidth(), (int)pg.getHeight());
}
@Override
diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFFreeformShape.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFFreeformShape.java
index 1f2352393..4f14fc1a8 100644
--- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFFreeformShape.java
+++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFFreeformShape.java
@@ -19,6 +19,7 @@
package org.apache.poi.xslf.usermodel;
+import java.awt.Rectangle;
import java.awt.geom.AffineTransform;
import java.awt.geom.GeneralPath;
import java.awt.geom.PathIterator;
@@ -60,7 +61,7 @@ public class XSLFFreeformShape extends XSLFAutoShape
public int setPath(GeneralPath path) {
CTPath2D ctPath = CTPath2D.Factory.newInstance();
- Rectangle2D bounds = path.getBounds2D();
+ Rectangle bounds = path.getBounds();
int x0 = Units.toEMU(bounds.getX());
int y0 = Units.toEMU(bounds.getY());
PathIterator it = path.getPathIterator(new AffineTransform());
diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFGraphicFrame.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFGraphicFrame.java
index 82a3fe1f6..930acd402 100644
--- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFGraphicFrame.java
+++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFGraphicFrame.java
@@ -19,7 +19,7 @@
package org.apache.poi.xslf.usermodel;
-import java.awt.geom.Rectangle2D;
+import java.awt.Rectangle;
import javax.xml.namespace.QName;
@@ -53,20 +53,19 @@ public class XSLFGraphicFrame extends XSLFShape {
throw new UnsupportedOperationException();
}
- public Rectangle2D getAnchor(){
+ @Override
+ public Rectangle getAnchor(){
CTTransform2D xfrm = ((CTGraphicalObjectFrame)getXmlObject()).getXfrm();
CTPoint2D off = xfrm.getOff();
- long x = off.getX();
- long y = off.getY();
+ int x = (int)Units.toPoints(off.getX());
+ int y = (int)Units.toPoints(off.getY());
CTPositiveSize2D ext = xfrm.getExt();
- long cx = ext.getCx();
- long cy = ext.getCy();
- return new Rectangle2D.Double(
- Units.toPoints(x), Units.toPoints(y),
- Units.toPoints(cx), Units.toPoints(cy));
+ int cx = (int)Units.toPoints(ext.getCx());
+ int cy = (int)Units.toPoints(ext.getCy());
+ return new Rectangle(x, y, cx, cy);
}
- public void setAnchor(Rectangle2D anchor){
+ public void setAnchor(Rectangle anchor){
CTTransform2D xfrm = ((CTGraphicalObjectFrame)getXmlObject()).getXfrm();
CTPoint2D off = xfrm.isSetOff() ? xfrm.getOff() : xfrm.addNewOff();
long x = Units.toEMU(anchor.getX());
diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFGroupShape.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFGroupShape.java
index 619950117..ae9c8bac6 100644
--- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFGroupShape.java
+++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFGroupShape.java
@@ -19,7 +19,7 @@
package org.apache.poi.xslf.usermodel;
-import java.awt.geom.Rectangle2D;
+import java.awt.Rectangle;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
@@ -27,6 +27,7 @@ import java.util.List;
import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.openxml4j.opc.PackageRelationship;
import org.apache.poi.openxml4j.opc.TargetMode;
+import org.apache.poi.sl.draw.DrawPictureShape;
import org.apache.poi.sl.usermodel.GroupShape;
import org.apache.poi.sl.usermodel.PictureData;
import org.apache.poi.util.Beta;
@@ -78,21 +79,19 @@ implements XSLFShapeContainer, GroupShape Note that in order to properly release resources the
+ * SlideShow should be closed after use. Note that in order to properly release resources theSlideShow should be closed after use.
+ *
+ * @param file The file to read data from.
+ * @param readOnly If the SlideShow should be opened in read-only mode to avoid writing back
+ * changes when the document is closed.
+ *
+ * @return The created SlideShow
+ *
+ * @throws IOException if an error occurs while reading the data
+ * @throws EncryptedDocumentException If the wrong password is given for a protected file
+ */
+ @SuppressWarnings("resource")
+ public static SlideShow,?> createSlideShow(File file, boolean readOnly)
+ throws IOException, InvalidFormatException {
+ OPCPackage pkg = OPCPackage.open(file, readOnly ? PackageAccess.READ : PackageAccess.READ_WRITE);
+ return createSlideShow(pkg);
+ }
+
+ /**
+ * Creates a XMLSlideShow from the given InputStream
+ *
+ * Note that in order to properly release resources the
+ * SlideShow should be closed after use.Rectangle2D
that is the bounds of this shape.
*/
- public Rectangle2D resizeToFitText(){
- Rectangle2D anchor = getAnchor();
+ public Rectangle resizeToFitText(){
+ Rectangle anchor = getAnchor();
if(anchor.getWidth() == 0.) throw new POIXMLException(
"Anchor of the shape was not set.");
double height = getTextHeight();
diff --git a/src/ooxml/java/org/apache/poi/xslf/util/PPTX2PNG.java b/src/ooxml/java/org/apache/poi/xslf/util/PPTX2PNG.java
index 9318a0894..2f9742693 100644
--- a/src/ooxml/java/org/apache/poi/xslf/util/PPTX2PNG.java
+++ b/src/ooxml/java/org/apache/poi/xslf/util/PPTX2PNG.java
@@ -31,10 +31,10 @@ import java.util.Map;
import javax.imageio.ImageIO;
-import org.apache.poi.sl.SlideShowFactory;
import org.apache.poi.sl.draw.Drawable;
import org.apache.poi.sl.usermodel.Slide;
import org.apache.poi.sl.usermodel.SlideShow;
+import org.apache.poi.sl.usermodel.SlideShowFactory;
import org.apache.poi.util.JvmBugs;
/**
diff --git a/src/ooxml/testcases/org/apache/poi/sl/draw/TestDrawPictureShape.java b/src/ooxml/testcases/org/apache/poi/sl/draw/TestDrawPictureShape.java
new file mode 100644
index 000000000..2fd0be313
--- /dev/null
+++ b/src/ooxml/testcases/org/apache/poi/sl/draw/TestDrawPictureShape.java
@@ -0,0 +1,71 @@
+/*
+ * ====================================================================
+ * 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.sl.draw;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.awt.Dimension;
+import java.awt.Rectangle;
+
+import org.apache.poi.POIDataSamples;
+import org.apache.poi.sl.usermodel.PictureData;
+import org.apache.poi.sl.usermodel.PictureShape;
+import org.apache.poi.sl.usermodel.RectAlign;
+import org.apache.poi.sl.usermodel.Shape;
+import org.apache.poi.sl.usermodel.Slide;
+import org.apache.poi.sl.usermodel.SlideShow;
+import org.apache.poi.sl.usermodel.SlideShowFactory;
+import org.junit.Test;
+
+public class TestDrawPictureShape {
+ final static POIDataSamples ssSamples = POIDataSamples.getSlideShowInstance();
+
+ @Test
+ public void testResize() throws Exception {
+ String files[] = { "pictures.ppt", "shapes.pptx" };
+ for (String file : files) {
+ SlideShow,?> ss = SlideShowFactory.create(ssSamples.getFile(file));
+ Slide,?> slide = ss.getSlides().get(0);
+ PictureShape,?> picShape = null;
+ for (Shape,?> shape : slide.getShapes()) {
+ if (shape instanceof PictureShape) {
+ picShape = (PictureShape,?>)shape;
+ break;
+ }
+ }
+ assertNotNull(picShape);
+ PictureData pd = picShape.getPictureData();
+ Dimension dimPd = pd.getImageDimension();
+ new DrawPictureShape(picShape).resize();
+ Dimension dimShape = picShape.getAnchor().getSize();
+ assertEquals(dimPd, dimShape);
+
+ int newWidth = (int)(dimPd.getWidth()*(100d/dimPd.getHeight()));
+ // ... -1 is a rounding error
+ Rectangle expRect = new Rectangle(50+300-newWidth-1, 50, newWidth, 100);
+ Rectangle target = new Rectangle(50,50,300,100);
+ new DrawPictureShape(picShape).resize(target, RectAlign.BOTTOM_RIGHT);
+ Rectangle actRect = picShape.getAnchor();
+ assertEquals(expRect, actRect);
+ }
+ }
+
+
+}
diff --git a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFGroupShape.java b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFGroupShape.java
index 4a6e0ff2a..f5d180121 100644
--- a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFGroupShape.java
+++ b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFGroupShape.java
@@ -16,10 +16,12 @@
==================================================================== */
package org.apache.poi.xslf.usermodel;
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
import java.awt.Dimension;
-import java.awt.geom.Rectangle2D;
+import java.awt.Rectangle;
import org.junit.Test;
@@ -29,7 +31,7 @@ import org.junit.Test;
public class TestXSLFGroupShape {
@Test
- public void testCreateShapes() {
+ public void testCreateShapes() throws Exception {
XMLSlideShow ppt = new XMLSlideShow();
XSLFSlide slide = ppt.createSlide();
@@ -38,11 +40,11 @@ public class TestXSLFGroupShape {
XSLFGroupShape group = slide.createGroup();
assertEquals(1, slide.getShapes().size());
- Rectangle2D interior = new Rectangle2D.Double(-10, -10, 20, 20);
+ Rectangle interior = new Rectangle(-10, -10, 20, 20);
group.setInteriorAnchor(interior);
assertEquals(interior, group.getInteriorAnchor());
- Rectangle2D anchor = new Rectangle2D.Double(0, 0, 792, 612);
+ Rectangle anchor = new Rectangle(0, 0, 792, 612);
group.setAnchor(anchor);
assertEquals(anchor, group.getAnchor());
@@ -83,10 +85,12 @@ public class TestXSLFGroupShape {
group.removeShape(shape1);
group.removeShape(shape4);
assertTrue(group.getShapes().isEmpty());
+
+ ppt.close();
}
@Test
- public void testRemoveShapes() {
+ public void testRemoveShapes() throws Exception {
XMLSlideShow ppt = new XMLSlideShow();
XSLFSlide slide = ppt.createSlide();
@@ -99,5 +103,6 @@ public class TestXSLFGroupShape {
slide.removeShape(group2);
slide.removeShape(group3);
+ ppt.close();
}
}
\ No newline at end of file
diff --git a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFSlideShowFactory.java b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFSlideShowFactory.java
new file mode 100644
index 000000000..8b9ac979f
--- /dev/null
+++ b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFSlideShowFactory.java
@@ -0,0 +1,66 @@
+/* ====================================================================
+ 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.xslf.usermodel;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.security.GeneralSecurityException;
+
+import org.apache.poi.POIDataSamples;
+import org.apache.poi.poifs.crypt.EncryptionInfo;
+import org.apache.poi.poifs.crypt.EncryptionMode;
+import org.apache.poi.poifs.crypt.Encryptor;
+import org.apache.poi.poifs.filesystem.NPOIFSFileSystem;
+import org.apache.poi.sl.usermodel.BaseTestSlideShowFactory;
+import org.apache.poi.util.IOUtils;
+import org.apache.poi.util.TempFile;
+import org.junit.Test;
+
+public final class TestXSLFSlideShowFactory extends BaseTestSlideShowFactory {
+ private static POIDataSamples _slTests = POIDataSamples.getSlideShowInstance();
+
+ @Test
+ public void testFactory() throws Exception {
+ File pFile = createProtected("SampleShow.pptx", "foobaa");
+ testFactory("SampleShow.pptx", pFile.getAbsolutePath(), "foobaa");
+ }
+
+ private static File createProtected(String basefile, String password)
+ throws IOException, GeneralSecurityException {
+ NPOIFSFileSystem fs = new NPOIFSFileSystem();
+ EncryptionInfo info = new EncryptionInfo(EncryptionMode.agile);
+ Encryptor enc = info.getEncryptor();
+ enc.confirmPassword(password);
+ InputStream fis = _slTests.openResourceAsStream("SampleShow.pptx");
+ OutputStream os = enc.getDataStream(fs);
+ IOUtils.copy(fis, os);
+ os.close();
+ fis.close();
+
+ File tf = TempFile.createTempFile("test-xslf-slidefactory", "pptx");
+ FileOutputStream fos = new FileOutputStream(tf);
+ fs.writeFilesystem(fos);
+ fos.close();
+ fs.close();
+
+ return tf;
+ }
+}
diff --git a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTextParagraph.java b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTextParagraph.java
index a2ddfadbb..a57771080 100644
--- a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTextParagraph.java
+++ b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTextParagraph.java
@@ -25,7 +25,6 @@ import static org.junit.Assert.assertTrue;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Rectangle;
-import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.List;
@@ -75,7 +74,7 @@ public class TestXSLFTextParagraph {
"of text within a shape. Properties here apply to all text " +
"residing within the corresponding paragraph.");
- Rectangle2D anchor = new Rectangle(50, 50, 300, 200);
+ Rectangle anchor = new Rectangle(50, 50, 300, 200);
sh.setAnchor(anchor);
DrawTextParagraphProxy dtp = new DrawTextParagraphProxy(p);
diff --git a/src/scratchpad/src/org/apache/poi/hslf/blip/Bitmap.java b/src/scratchpad/src/org/apache/poi/hslf/blip/Bitmap.java
index c25d7de84..f584bd8a8 100644
--- a/src/scratchpad/src/org/apache/poi/hslf/blip/Bitmap.java
+++ b/src/scratchpad/src/org/apache/poi/hslf/blip/Bitmap.java
@@ -26,6 +26,7 @@ import java.io.IOException;
import javax.imageio.ImageIO;
import org.apache.poi.hslf.usermodel.HSLFPictureData;
+import org.apache.poi.util.Units;
/**
* Represents a bitmap picture data: JPEG or PNG.
@@ -55,10 +56,14 @@ public abstract class Bitmap extends HSLFPictureData {
setRawData(out.toByteArray());
}
+ @Override
public Dimension getImageDimension() {
try {
BufferedImage bi = ImageIO.read(new ByteArrayInputStream(getData()));
- return new Dimension(bi.getWidth(), bi.getHeight());
+ return new Dimension(
+ (int)Units.pixelToPoints(bi.getWidth()),
+ (int)Units.pixelToPoints(bi.getHeight())
+ );
} catch (IOException e) {
return new Dimension(200,200);
}
diff --git a/src/scratchpad/src/org/apache/poi/hslf/blip/Metafile.java b/src/scratchpad/src/org/apache/poi/hslf/blip/Metafile.java
index 74a793f5a..55a62ebff 100644
--- a/src/scratchpad/src/org/apache/poi/hslf/blip/Metafile.java
+++ b/src/scratchpad/src/org/apache/poi/hslf/blip/Metafile.java
@@ -126,7 +126,7 @@ public abstract class Metafile extends HSLFPictureData {
return out.toByteArray();
}
-
+ @Override
public Dimension getImageDimension() {
int prefixLen = 16*uidInstanceCount;
Header header = new Header();
diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/PPGraphics2D.java b/src/scratchpad/src/org/apache/poi/hslf/model/PPGraphics2D.java
index 7ba654c02..834dea5ff 100644
--- a/src/scratchpad/src/org/apache/poi/hslf/model/PPGraphics2D.java
+++ b/src/scratchpad/src/org/apache/poi/hslf/model/PPGraphics2D.java
@@ -42,7 +42,6 @@ import java.awt.geom.Arc2D;
import java.awt.geom.Ellipse2D;
import java.awt.geom.GeneralPath;
import java.awt.geom.Line2D;
-import java.awt.geom.Rectangle2D;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
import java.awt.image.BufferedImageOp;
@@ -327,7 +326,7 @@ public final class PPGraphics2D extends Graphics2D implements Cloneable {
Java graphics sets string coordinates by the baseline of the first character
so we need to shift down by the height of the textbox
*/
- txt.setAnchor(new Rectangle2D.Float(x, y, width, height));
+ txt.setAnchor(new Rectangle((int)x, (int)y, (int)width, (int)height));
_group.addShape(txt);
}
diff --git a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFFreeformShape.java b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFFreeformShape.java
index e576cceef..dbfc6ec1f 100644
--- a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFFreeformShape.java
+++ b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFFreeformShape.java
@@ -17,6 +17,7 @@
package org.apache.poi.hslf.usermodel;
+import java.awt.Rectangle;
import java.awt.geom.AffineTransform;
import java.awt.geom.GeneralPath;
import java.awt.geom.PathIterator;
@@ -45,7 +46,6 @@ import org.apache.poi.util.Units;
* Shapes drawn with the "Freeform" tool have cubic bezier curve segments in the smooth sections
* and straight-line segments in the straight sections. This object closely corresponds to java.awt.geom.GeneralPath
.
*
Rectangle2D
that is the bounds of this shape.
*/
public Rectangle2D resizeToFitText(){
- Rectangle2D anchor = getAnchor();
+ Rectangle anchor = getAnchor();
if(anchor.getWidth() == 0.) {
logger.log(POILogger.WARN, "Width of shape wasn't set. Defaulting to 200px");
- anchor = new Rectangle2D.Double(anchor.getX(), anchor.getY(), 200, anchor.getHeight());
+ anchor.setSize(200, (int)anchor.getHeight());
setAnchor(anchor);
}
double height = getTextHeight();
diff --git a/src/scratchpad/testcases/org/apache/poi/hslf/model/TestMovieShape.java b/src/scratchpad/testcases/org/apache/poi/hslf/model/TestMovieShape.java
index df696d021..7b6e762cf 100644
--- a/src/scratchpad/testcases/org/apache/poi/hslf/model/TestMovieShape.java
+++ b/src/scratchpad/testcases/org/apache/poi/hslf/model/TestMovieShape.java
@@ -21,7 +21,7 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
-import java.awt.geom.Rectangle2D;
+import java.awt.Rectangle;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
@@ -34,8 +34,6 @@ import org.junit.Test;
/**
* Test MovieShape
object.
- *
- * @author Yegor Kozlov
*/
public final class TestMovieShape {
@@ -52,7 +50,7 @@ public final class TestMovieShape {
HSLFPictureData thumbnailData = ppt.addPicture(_slTests.readFile("tomcat.png"), PictureType.PNG);
MovieShape shape = new MovieShape(movieIdx, thumbnailData);
- shape.setAnchor(new Rectangle2D.Float(300,225,120,90));
+ shape.setAnchor(new Rectangle(300,225,120,90));
slide.addShape(shape);
assertEquals(path, shape.getPath());
diff --git a/src/scratchpad/testcases/org/apache/poi/hslf/model/TestOleEmbedding.java b/src/scratchpad/testcases/org/apache/poi/hslf/model/TestOleEmbedding.java
index a03c25313..5babd1bf8 100644
--- a/src/scratchpad/testcases/org/apache/poi/hslf/model/TestOleEmbedding.java
+++ b/src/scratchpad/testcases/org/apache/poi/hslf/model/TestOleEmbedding.java
@@ -20,18 +20,26 @@ package org.apache.poi.hslf.model;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
-import java.awt.geom.Rectangle2D;
-import java.io.*;
+import java.awt.Rectangle;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.InputStream;
import java.util.List;
import org.apache.poi.POIDataSamples;
-import org.apache.poi.hslf.usermodel.*;
+import org.apache.poi.hslf.usermodel.HSLFObjectData;
+import org.apache.poi.hslf.usermodel.HSLFPictureData;
+import org.apache.poi.hslf.usermodel.HSLFShape;
+import org.apache.poi.hslf.usermodel.HSLFSlide;
+import org.apache.poi.hslf.usermodel.HSLFSlideShow;
+import org.apache.poi.hslf.usermodel.HSLFSlideShowImpl;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hwpf.HWPFDocument;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
-import org.apache.poi.util.IOUtils;
import org.apache.poi.sl.usermodel.PictureData.PictureType;
+import org.apache.poi.util.IOUtils;
import org.junit.Test;
public final class TestOleEmbedding {
@@ -109,7 +117,7 @@ public final class TestOleEmbedding {
OLEShape oleShape1 = new OLEShape(pictData);
oleShape1.setObjectID(oleObjectId1);
slide1.addShape(oleShape1);
- oleShape1.setAnchor(new Rectangle2D.Double(100,100,100,100));
+ oleShape1.setAnchor(new Rectangle(100,100,100,100));
// add second slide with different order in object creation
HSLFSlide slide2 = ppt.createSlide();
@@ -123,7 +131,7 @@ public final class TestOleEmbedding {
oleShape2.setObjectID(oleObjectId2);
slide2.addShape(oleShape2);
- oleShape2.setAnchor(new Rectangle2D.Double(100,100,100,100));
+ oleShape2.setAnchor(new Rectangle(100,100,100,100));
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ppt.write(bos);
diff --git a/src/scratchpad/testcases/org/apache/poi/hslf/model/TestShapes.java b/src/scratchpad/testcases/org/apache/poi/hslf/model/TestShapes.java
index 3dfdd5783..f7fe4c43f 100644
--- a/src/scratchpad/testcases/org/apache/poi/hslf/model/TestShapes.java
+++ b/src/scratchpad/testcases/org/apache/poi/hslf/model/TestShapes.java
@@ -27,7 +27,6 @@ import static org.junit.Assert.assertTrue;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Rectangle;
-import java.awt.geom.Rectangle2D;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
@@ -63,8 +62,6 @@ import org.junit.Test;
/**
* Test drawing shapes via Graphics2D
- *
- * @author Yegor Kozlov
*/
public final class TestShapes {
private static POIDataSamples _slTests = POIDataSamples.getSlideShowInstance();
@@ -165,8 +162,8 @@ public final class TestShapes {
@SuppressWarnings("unused")
@Test
public void testParagraphs() throws Exception {
- HSLFSlideShow ppt = new HSLFSlideShow();
- HSLFSlide slide = ppt.createSlide();
+ HSLFSlideShow ss = new HSLFSlideShow();
+ HSLFSlide slide = ss.createSlide();
HSLFTextBox shape = new HSLFTextBox();
HSLFTextRun p1r1 = shape.setText("para 1 run 1. ");
HSLFTextRun p1r2 = shape.appendText("para 1 run 2.", false);
@@ -178,15 +175,15 @@ public final class TestShapes {
p2r2.setStrikethrough(true);
// run 3 has same text properties as run 2 and will be merged when saving
HSLFTextRun p2r3 = shape.appendText("para 2 run 3.", false);
- shape.setAnchor(new Rectangle2D.Double(100,100,100,10));
+ shape.setAnchor(new Rectangle(100,100,100,10));
slide.addShape(shape);
shape.resizeToFitText();
ByteArrayOutputStream bos = new ByteArrayOutputStream();
- ppt.write(bos);
+ ss.write(bos);
- ppt = new HSLFSlideShow(new ByteArrayInputStream(bos.toByteArray()));
- slide = ppt.getSlides().get(0);
+ ss = new HSLFSlideShow(new ByteArrayInputStream(bos.toByteArray()));
+ slide = ss.getSlides().get(0);
HSLFTextBox tb = (HSLFTextBox)slide.getShapes().get(0);
List