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 { } @Override - public Rectangle2D getAnchor(){ + public Rectangle getAnchor(){ CTGroupTransform2D xfrm = 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); } @Override - public void setAnchor(Rectangle2D anchor){ + public void setAnchor(Rectangle anchor){ CTGroupTransform2D xfrm = getSafeXfrm(); CTPoint2D off = xfrm.isSetOff() ? xfrm.getOff() : xfrm.addNewOff(); long x = Units.toEMU(anchor.getX()); @@ -112,17 +111,15 @@ implements XSLFShapeContainer, GroupShape { * used for calculations of grouping, scaling, and rotation * behavior of shapes placed within a group. */ - public Rectangle2D getInteriorAnchor(){ + public Rectangle getInteriorAnchor(){ CTGroupTransform2D xfrm = getXfrm(); CTPoint2D off = xfrm.getChOff(); - 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.getChExt(); - 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); } /** @@ -131,7 +128,7 @@ implements XSLFShapeContainer, GroupShape { * used for calculations of grouping, scaling, and rotation * behavior of shapes placed within a group. */ - public void setInteriorAnchor(Rectangle2D anchor) { + public void setInteriorAnchor(Rectangle anchor) { CTGroupTransform2D xfrm = getSafeXfrm(); CTPoint2D off = xfrm.isSetChOff() ? xfrm.getChOff() : xfrm.addNewChOff(); long x = Units.toEMU(anchor.getX()); @@ -250,7 +247,7 @@ implements XSLFShapeContainer, GroupShape { pic.getPartName(), TargetMode.INTERNAL, XSLFRelation.IMAGES.getRelation()); XSLFPictureShape sh = getDrawing().createPicture(rel.getId()); - sh.resize(); + new DrawPictureShape(sh).resize(); _shapes.add(sh); sh.setParent(this); return sh; diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFPictureData.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFPictureData.java index b2d407d23..cd3cbf056 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFPictureData.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFPictureData.java @@ -42,6 +42,7 @@ import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LittleEndianConsts; import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogger; +import org.apache.poi.util.Units; /** * Instantiates sub-classes of POIXMLDocumentPart depending on their relationship type @@ -134,6 +135,15 @@ public final class XSLFPictureData extends POIXMLDocumentPart implements Picture return _origSize; } + @Override + public Dimension getImageDimensionInPixels() { + Dimension dim = getImageDimension(); + return new Dimension( + Units.pointsToPixel(dim.getWidth()), + Units.pointsToPixel(dim.getHeight()) + ); + } + /** * Determine and cache image properties */ @@ -155,14 +165,19 @@ public final class XSLFPictureData extends POIXMLDocumentPart implements Picture _origSize = new PICT.NativeHeader(data, 0).getSize(); break; default: + BufferedImage img = null; try { - BufferedImage img = ImageIO.read(new ByteArrayInputStream(data)); - _origSize = (img == null) ? new Dimension() : new Dimension(img.getWidth(), img.getHeight()); + img = ImageIO.read(new ByteArrayInputStream(data)); } catch (IOException e) { logger.log(POILogger.WARN, "Can't determine image dimensions", e); - // failed to get information, set dummy size - _origSize = new Dimension(200,200); } + // set dummy size, in case of dummy dimension can't be set + _origSize = (img == null) + ? new Dimension(200,200) + : new Dimension( + (int)Units.pixelToPoints(img.getWidth()), + (int)Units.pixelToPoints(img.getHeight()) + ); break; } } diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFPictureShape.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFPictureShape.java index df352b57d..44de46e1e 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFPictureShape.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFPictureShape.java @@ -19,10 +19,9 @@ package org.apache.poi.xslf.usermodel; -import java.awt.Dimension; import java.awt.Insets; -import java.awt.Rectangle; import java.net.URI; + import javax.xml.namespace.QName; import org.apache.poi.POIXMLException; @@ -83,24 +82,6 @@ public class XSLFPictureShape extends XSLFSimpleShape return ct; } - /** - * Resize this picture to the default size. - * - * For PNG and JPEG resizes the image to 100%, - * for other types sets the default size to 200x200 pixels. - */ - public void resize() { - Dimension dim = getPictureData().getImageDimension(); - if (dim.width > 0 && dim.height > 0) - { - setAnchor(new Rectangle(0, 0, dim.width, dim.height)); - } - else - { - // unsupported/unknown formats - setAnchor(new Rectangle(50, 50, 200, 200)); - } - } /** * Is this an internal picture (image data included within diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFShadow.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFShadow.java index fd42bc2d7..f5d41c293 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFShadow.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFShadow.java @@ -18,7 +18,7 @@ package org.apache.poi.xslf.usermodel; import java.awt.Color; -import java.awt.geom.Rectangle2D; +import java.awt.Rectangle; import org.apache.poi.sl.draw.DrawPaint; import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint; @@ -32,7 +32,7 @@ import org.openxmlformats.schemas.drawingml.x2006.main.CTSchemeColor; * * @author Yegor Kozlov */ -public class XSLFShadow extends XSLFShape implements Shadow { +public class XSLFShadow extends XSLFShape implements Shadow { private XSLFSimpleShape _parent; @@ -47,11 +47,12 @@ public class XSLFShadow extends XSLFShape implements Shadow { return _parent; } - public Rectangle2D getAnchor(){ + @Override + public Rectangle getAnchor(){ return _parent.getAnchor(); } - public void setAnchor(Rectangle2D anchor){ + public void setAnchor(Rectangle anchor){ throw new IllegalStateException("You can't set anchor of a shadow"); } diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSheet.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSheet.java index 627f97310..f5d0207b7 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSheet.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSheet.java @@ -36,6 +36,7 @@ import org.apache.poi.openxml4j.opc.PackagePartName; import org.apache.poi.openxml4j.opc.PackageRelationship; import org.apache.poi.openxml4j.opc.TargetMode; import org.apache.poi.sl.draw.DrawFactory; +import org.apache.poi.sl.draw.DrawPictureShape; import org.apache.poi.sl.draw.Drawable; import org.apache.poi.sl.usermodel.PictureData; import org.apache.poi.sl.usermodel.Sheet; @@ -213,7 +214,7 @@ implements XSLFShapeContainer, Sheet { addRelation(rel.getId(), new XSLFPictureData(pic, rel)); XSLFPictureShape sh = getDrawing().createPicture(rel.getId()); - sh.resize(); + new DrawPictureShape(sh).resize(); getShapes().add(sh); sh.setParent(this); return sh; @@ -537,6 +538,7 @@ implements XSLFShapeContainer, Sheet { * @param packagePart package part containing the data to import * @return ID of the created relationship */ + @SuppressWarnings("resource") String importBlip(String blipId, PackagePart packagePart) { PackageRelationship blipRel = packagePart.getRelationship(blipId); PackagePart blipPart; @@ -561,6 +563,7 @@ implements XSLFShapeContainer, Sheet { /** * Import a package part into this sheet. */ + @SuppressWarnings("resource") PackagePart importPart(PackageRelationship srcRel, PackagePart srcPafrt) { PackagePart destPP = getPackagePart(); PackagePartName srcPPName = srcPafrt.getPartName(); @@ -574,10 +577,11 @@ implements XSLFShapeContainer, Sheet { destPP.addRelationship(srcPPName, TargetMode.INTERNAL, srcRel.getRelationshipType()); PackagePart part = pkg.createPart(srcPPName, srcPafrt.getContentType()); - OutputStream out = part.getOutputStream(); try { + OutputStream out = part.getOutputStream(); InputStream is = srcPafrt.getInputStream(); IOUtils.copy(is, out); + is.close(); out.close(); } catch (IOException e){ throw new POIXMLException(e); diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSimpleShape.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSimpleShape.java index 4ada16bf8..821cb07df 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSimpleShape.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSimpleShape.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 javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamReader; @@ -45,7 +45,33 @@ import org.apache.poi.util.Beta; import org.apache.poi.util.Units; import org.apache.poi.xslf.model.PropertyFetcher; import org.apache.xmlbeans.XmlObject; -import org.openxmlformats.schemas.drawingml.x2006.main.*; +import org.openxmlformats.schemas.drawingml.x2006.main.CTBaseStyles; +import org.openxmlformats.schemas.drawingml.x2006.main.CTBlip; +import org.openxmlformats.schemas.drawingml.x2006.main.CTEffectStyleItem; +import org.openxmlformats.schemas.drawingml.x2006.main.CTGeomGuide; +import org.openxmlformats.schemas.drawingml.x2006.main.CTLineEndProperties; +import org.openxmlformats.schemas.drawingml.x2006.main.CTLineProperties; +import org.openxmlformats.schemas.drawingml.x2006.main.CTLineStyleList; +import org.openxmlformats.schemas.drawingml.x2006.main.CTOuterShadowEffect; +import org.openxmlformats.schemas.drawingml.x2006.main.CTPoint2D; +import org.openxmlformats.schemas.drawingml.x2006.main.CTPositiveSize2D; +import org.openxmlformats.schemas.drawingml.x2006.main.CTPresetGeometry2D; +import org.openxmlformats.schemas.drawingml.x2006.main.CTPresetLineDashProperties; +import org.openxmlformats.schemas.drawingml.x2006.main.CTSRgbColor; +import org.openxmlformats.schemas.drawingml.x2006.main.CTSchemeColor; +import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeProperties; +import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeStyle; +import org.openxmlformats.schemas.drawingml.x2006.main.CTSolidColorFillProperties; +import org.openxmlformats.schemas.drawingml.x2006.main.CTStyleMatrix; +import org.openxmlformats.schemas.drawingml.x2006.main.CTStyleMatrixReference; +import org.openxmlformats.schemas.drawingml.x2006.main.CTTransform2D; +import org.openxmlformats.schemas.drawingml.x2006.main.STCompoundLine; +import org.openxmlformats.schemas.drawingml.x2006.main.STLineCap; +import org.openxmlformats.schemas.drawingml.x2006.main.STLineEndLength; +import org.openxmlformats.schemas.drawingml.x2006.main.STLineEndType; +import org.openxmlformats.schemas.drawingml.x2006.main.STLineEndWidth; +import org.openxmlformats.schemas.drawingml.x2006.main.STPresetLineDashVal; +import org.openxmlformats.schemas.drawingml.x2006.main.STShapeType; import org.openxmlformats.schemas.presentationml.x2006.main.CTPlaceholder; /** @@ -97,23 +123,21 @@ public abstract class XSLFSimpleShape extends XSLFShape } @Override - public Rectangle2D getAnchor() { + public Rectangle getAnchor() { CTTransform2D xfrm = 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); } @Override - public void setAnchor(Rectangle2D anchor) { + public void setAnchor(Rectangle anchor) { CTTransform2D xfrm = getSafeXfrm(); 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/XSLFSlideShowFactory.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSlideShowFactory.java new file mode 100644 index 000000000..346d81b73 --- /dev/null +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSlideShowFactory.java @@ -0,0 +1,100 @@ +/* ==================================================================== + 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.IOException; +import java.io.InputStream; + +import org.apache.poi.EncryptedDocumentException; +import org.apache.poi.openxml4j.exceptions.InvalidFormatException; +import org.apache.poi.openxml4j.opc.OPCPackage; +import org.apache.poi.openxml4j.opc.PackageAccess; +import org.apache.poi.sl.usermodel.SlideShow; +import org.apache.poi.sl.usermodel.SlideShowFactory; +import org.apache.poi.util.Internal; + +@Internal +public class XSLFSlideShowFactory extends SlideShowFactory { + + /** + * Creates a XMLSlideShow from the given OOXML Package + * + *

Note that in order to properly release resources the + * SlideShow should be closed after use.

+ * + * @param pkg The {@link OPCPackage} opened for reading data. + * + * @return The created SlideShow + * + * @throws IOException if an error occurs while reading the data + * @throws InvalidFormatException + */ + public static SlideShow createSlideShow(OPCPackage pkg) throws IOException { + try { + return new XMLSlideShow(pkg); + } catch (IllegalArgumentException ioe) { + // ensure that file handles are closed (use revert() to not re-write the file) + pkg.revert(); + //pkg.close(); + + // rethrow exception + throw ioe; + } + } + + /** + * Creates the XMLSlideShow from the given File, which must exist and be readable. + *

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.

+ * + * @param stream The {@link InputStream} to read data from. + * + * @return The created SlideShow + * + * @throws IOException if an error occurs while reading the data + * @throws InvalidFormatException + */ + @SuppressWarnings("resource") + public static SlideShow createSlideShow(InputStream stream) throws IOException, InvalidFormatException { + OPCPackage pkg = OPCPackage.open(stream); + return createSlideShow(pkg); + } + +} diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextShape.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextShape.java index 034b50cdd..8cc90f979 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextShape.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextShape.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; @@ -466,8 +466,8 @@ public abstract class XSLFTextShape extends XSLFSimpleShape * * @return a 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. *

- * @author Yegor Kozlov */ public final class HSLFFreeformShape extends HSLFAutoShape implements FreeformShape { @@ -90,7 +90,7 @@ public final class HSLFFreeformShape extends HSLFAutoShape implements FreeformSh @Override public int setPath(GeneralPath path) { - Rectangle2D bounds = path.getBounds2D(); + Rectangle bounds = path.getBounds(); PathIterator it = path.getPathIterator(new AffineTransform()); List segInfo = new ArrayList(); @@ -241,7 +241,7 @@ public final class HSLFFreeformShape extends HSLFAutoShape implements FreeformSh } } - Rectangle2D anchor = getAnchor2D(); + Rectangle2D anchor = getAnchor(); Rectangle2D bounds = path.getBounds2D(); AffineTransform at = new AffineTransform(); at.translate(anchor.getX(), anchor.getY()); diff --git a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFGroupShape.java b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFGroupShape.java index 0ba1d379b..22317fb62 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFGroupShape.java +++ b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFGroupShape.java @@ -18,7 +18,6 @@ package org.apache.poi.hslf.usermodel; import java.awt.Rectangle; -import java.awt.geom.Rectangle2D; import java.util.ArrayList; import java.util.Iterator; import java.util.List; @@ -105,7 +104,7 @@ implements HSLFShapeContainer, GroupShape { } @Override - public void setInteriorAnchor(Rectangle2D anchor){ + public void setInteriorAnchor(Rectangle anchor){ EscherSpgrRecord spgr = getEscherChild(EscherSpgrRecord.RECORD_ID); int x1 = Units.pointsToMaster(anchor.getX()); @@ -121,13 +120,13 @@ implements HSLFShapeContainer, GroupShape { } @Override - public Rectangle2D getInteriorAnchor(){ + public Rectangle getInteriorAnchor(){ EscherSpgrRecord rec = getEscherChild(EscherSpgrRecord.RECORD_ID); - double x1 = Units.masterToPoints(rec.getRectX1()); - double y1 = Units.masterToPoints(rec.getRectY1()); - double x2 = Units.masterToPoints(rec.getRectX2()); - double y2 = Units.masterToPoints(rec.getRectY2()); - return new Rectangle2D.Double(x1,y1,x2-x1,y2-y1); + int x1 = (int)Units.masterToPoints(rec.getRectX1()); + int y1 = (int)Units.masterToPoints(rec.getRectY1()); + int x2 = (int)Units.masterToPoints(rec.getRectX2()); + int y2 = (int)Units.masterToPoints(rec.getRectY2()); + return new Rectangle(x1,y1,x2-x1,y2-y1); } /** @@ -181,7 +180,7 @@ implements HSLFShapeContainer, GroupShape { * @param y the y coordinate of the top left corner of the shape in new location */ public void moveTo(int x, int y){ - java.awt.Rectangle anchor = getAnchor(); + Rectangle anchor = getAnchor(); int dx = x - anchor.x; int dy = y - anchor.y; anchor.translate(dx, dy); @@ -189,7 +188,7 @@ implements HSLFShapeContainer, GroupShape { for (HSLFShape shape : getShapes()) { - java.awt.Rectangle chanchor = shape.getAnchor(); + Rectangle chanchor = shape.getAnchor(); chanchor.translate(dx, dy); shape.setAnchor(chanchor); } @@ -201,7 +200,7 @@ implements HSLFShapeContainer, GroupShape { * * @return the anchor of this shape group */ - public Rectangle2D getAnchor2D(){ + public Rectangle getAnchor(){ EscherClientAnchorRecord clientAnchor = getEscherChild(EscherClientAnchorRecord.RECORD_ID); int x1,y1,x2,y2; if(clientAnchor == null){ @@ -217,11 +216,11 @@ implements HSLFShapeContainer, GroupShape { x2 = clientAnchor.getDx1(); y2 = clientAnchor.getRow1(); } - Rectangle2D anchor= new Rectangle2D.Double( - (x1 == -1 ? -1 : Units.masterToPoints(x1)), - (y1 == -1 ? -1 : Units.masterToPoints(y1)), - (x2 == -1 ? -1 : Units.masterToPoints(x2-x1)), - (y2 == -1 ? -1 : Units.masterToPoints(y2-y1)) + Rectangle anchor= new Rectangle( + (int)(x1 == -1 ? -1 : Units.masterToPoints(x1)), + (int)(y1 == -1 ? -1 : Units.masterToPoints(y1)), + (int)(x2 == -1 ? -1 : Units.masterToPoints(x2-x1)), + (int)(y2 == -1 ? -1 : Units.masterToPoints(y2-y1)) ); return anchor; diff --git a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFPictureData.java b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFPictureData.java index 0100658fe..7c5fc5179 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFPictureData.java +++ b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFPictureData.java @@ -17,6 +17,7 @@ package org.apache.poi.hslf.usermodel; +import java.awt.Dimension; import java.io.IOException; import java.io.OutputStream; import java.security.MessageDigest; @@ -219,4 +220,13 @@ public abstract class HSLFPictureData implements PictureData { public final String getContentType() { return getType().contentType; } + + @Override + public Dimension getImageDimensionInPixels() { + Dimension dim = getImageDimension(); + return new Dimension( + Units.pointsToPixel(dim.getWidth()), + Units.pointsToPixel(dim.getHeight()) + ); + } } diff --git a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFPictureShape.java b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFPictureShape.java index 58ce1a1f2..713ecad70 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFPictureShape.java +++ b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFPictureShape.java @@ -17,9 +17,8 @@ package org.apache.poi.hslf.usermodel; -import java.awt.Dimension; import java.awt.Insets; -import java.awt.geom.Rectangle2D; +import java.awt.Rectangle; import java.util.List; import org.apache.poi.ddf.AbstractEscherOptRecord; @@ -31,6 +30,7 @@ import org.apache.poi.ddf.EscherRecord; import org.apache.poi.ddf.EscherSimpleProperty; import org.apache.poi.ddf.EscherSpRecord; import org.apache.poi.hslf.record.Document; +import org.apache.poi.sl.draw.DrawPictureShape; import org.apache.poi.sl.usermodel.PictureShape; import org.apache.poi.sl.usermodel.ShapeContainer; import org.apache.poi.sl.usermodel.ShapeType; @@ -113,21 +113,6 @@ public class HSLFPictureShape extends HSLFSimpleShape implements PictureShape @@ -126,18 +141,7 @@ public abstract class HSLFShape implements Shape { * * @return the anchor of this shape */ - public java.awt.Rectangle getAnchor(){ - Rectangle2D anchor2d = getAnchor2D(); - return anchor2d.getBounds(); - } - - /** - * Returns the anchor (the bounding box rectangle) of this shape. - * All coordinates are expressed in points (72 dpi). - * - * @return the anchor of this shape - */ - public Rectangle2D getAnchor2D(){ + public Rectangle getAnchor() { EscherSpRecord spRecord = getEscherChild(EscherSpRecord.RECORD_ID); int flags = spRecord.getFlags(); int x1,y1,x2,y2; @@ -160,11 +164,11 @@ public abstract class HSLFShape implements Shape { } // TODO: find out where this -1 value comes from at #57820 (link to ms docs?) - Rectangle2D anchor = new Rectangle2D.Double( - (x1 == -1 ? -1 : Units.masterToPoints(x1)), - (y1 == -1 ? -1 : Units.masterToPoints(y1)), - (x2 == -1 ? -1 : Units.masterToPoints(x2-x1)), - (y2 == -1 ? -1 : Units.masterToPoints(y2-y1)) + Rectangle anchor = new Rectangle( + (int)(x1 == -1 ? -1 : Units.masterToPoints(x1)), + (int)(y1 == -1 ? -1 : Units.masterToPoints(y1)), + (int)(x2 == -1 ? -1 : Units.masterToPoints(x2-x1)), + (int)(y2 == -1 ? -1 : Units.masterToPoints(y2-y1)) ); return anchor; @@ -176,7 +180,7 @@ public abstract class HSLFShape implements Shape { * * @param anchor new anchor */ - public void setAnchor(Rectangle2D anchor){ + public void setAnchor(Rectangle anchor){ int x = Units.pointsToMaster(anchor.getX()); int y = Units.pointsToMaster(anchor.getY()); int w = Units.pointsToMaster(anchor.getWidth() + anchor.getX()); @@ -206,7 +210,7 @@ public abstract class HSLFShape implements Shape { * @param y the y coordinate of the top left corner of the shape */ public void moveTo(float x, float y){ - Rectangle2D anchor = getAnchor2D(); + Rectangle anchor = getAnchor(); anchor.setRect(x, y, anchor.getWidth(), anchor.getHeight()); setAnchor(anchor); } diff --git a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSimpleShape.java b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSimpleShape.java index aeb36beb5..dc5cde23d 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSimpleShape.java +++ b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSimpleShape.java @@ -414,12 +414,12 @@ public abstract class HSLFSimpleShape extends HSLFShape implements SimpleShape getShadow() { AbstractEscherOptRecord opt = getEscherOptRecord(); EscherProperty shadowType = opt.lookup(EscherProperties.SHADOWSTYLE__TYPE); if (shadowType == null) return null; - return new Shadow(){ + return new Shadow(){ public SimpleShape getShadowParent() { return HSLFSimpleShape.this; } diff --git a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlideShow.java b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlideShow.java index 697f10521..c300bd81c 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlideShow.java +++ b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlideShow.java @@ -69,6 +69,7 @@ import org.apache.poi.hslf.record.SlideListWithText.SlideAtomsSet; import org.apache.poi.hslf.record.SlidePersistAtom; import org.apache.poi.hslf.record.UserEditAtom; import org.apache.poi.poifs.filesystem.DirectoryNode; +import org.apache.poi.poifs.filesystem.NPOIFSFileSystem; import org.apache.poi.poifs.filesystem.POIFSFileSystem; import org.apache.poi.sl.usermodel.MasterSheet; import org.apache.poi.sl.usermodel.PictureData.PictureType; @@ -159,8 +160,8 @@ public final class HSLFSlideShow implements SlideShowNote that in order to properly release resources the + * SlideShow should be closed after use. + */ + public static SlideShow createSlideShow(NPOIFSFileSystem fs) throws IOException { + return new HSLFSlideShow(fs); + } + +} diff --git a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTextShape.java b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTextShape.java index 5ca39b991..1b5bbb83f 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTextShape.java +++ b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTextShape.java @@ -139,15 +139,15 @@ implements TextShape { storeText(); - EscherTextboxWrapper _txtbox = getEscherTextboxWrapper(); - if(_txtbox != null){ - _escherContainer.addChildRecord(_txtbox.getEscherRecord()); + EscherTextboxWrapper thisTxtbox = getEscherTextboxWrapper(); + if(thisTxtbox != null){ + _escherContainer.addChildRecord(thisTxtbox.getEscherRecord()); PPDrawing ppdrawing = sh.getPPDrawing(); - ppdrawing.addTextboxWrapper(_txtbox); + ppdrawing.addTextboxWrapper(thisTxtbox); // Ensure the escher layer knows about the added records try { - _txtbox.writeOut(null); + thisTxtbox.writeOut(null); } catch (IOException e){ throw new HSLFException(e); } @@ -192,10 +192,10 @@ implements TextShape { * @return a 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 para = tb.getTextParagraphs(); HSLFTextRun tr = para.get(0).getTextRuns().get(0); @@ -289,8 +286,8 @@ public final class TestShapes { } private void textBoxSet(String filename) throws Exception { - HSLFSlideShow ppt = new HSLFSlideShow(_slTests.openResourceAsStream(filename)); - for (HSLFSlide sld : ppt.getSlides()) { + HSLFSlideShow ss = new HSLFSlideShow(_slTests.openResourceAsStream(filename)); + for (HSLFSlide sld : ss.getSlides()) { ArrayList lst1 = new ArrayList(); for (List txt : sld.getTextParagraphs()) { for (HSLFTextParagraph p : txt) { @@ -321,17 +318,17 @@ public final class TestShapes { */ @Test public void shapeGroup() throws Exception { - HSLFSlideShow ppt = new HSLFSlideShow(); + HSLFSlideShow ss = new HSLFSlideShow(); - HSLFSlide slide = ppt.createSlide(); - Dimension pgsize = ppt.getPageSize(); + HSLFSlide slide = ss.createSlide(); + Dimension pgsize = ss.getPageSize(); HSLFGroupShape group = new HSLFGroupShape(); group.setAnchor(new Rectangle(0, 0, (int)pgsize.getWidth(), (int)pgsize.getHeight())); slide.addShape(group); - HSLFPictureData data = ppt.addPicture(_slTests.readFile("clock.jpg"), PictureType.JPEG); + HSLFPictureData data = ss.addPicture(_slTests.readFile("clock.jpg"), PictureType.JPEG); HSLFPictureShape pict = new HSLFPictureShape(data, group); pict.setAnchor(new Rectangle(0, 0, 200, 200)); group.addShape(pict); @@ -342,14 +339,14 @@ public final class TestShapes { //serialize and read again. ByteArrayOutputStream out = new ByteArrayOutputStream(); - ppt.write(out); + ss.write(out); out.close(); ByteArrayInputStream is = new ByteArrayInputStream(out.toByteArray()); - ppt = new HSLFSlideShow(is); + ss = new HSLFSlideShow(is); is.close(); - slide = ppt.getSlides().get(0); + slide = ss.getSlides().get(0); List shape = slide.getShapes(); assertEquals(1, shape.size()); @@ -374,8 +371,8 @@ public final class TestShapes { @Test public void removeShapes() throws IOException { String file = "with_textbox.ppt"; - HSLFSlideShow ppt = new HSLFSlideShow(_slTests.openResourceAsStream(file)); - HSLFSlide sl = ppt.getSlides().get(0); + HSLFSlideShow ss = new HSLFSlideShow(_slTests.openResourceAsStream(file)); + HSLFSlide sl = ss.getSlides().get(0); List sh = sl.getShapes(); assertEquals("expected four shaped in " + file, 4, sh.size()); //remove all @@ -388,11 +385,11 @@ public final class TestShapes { //serialize and read again. The file should be readable and contain no shapes ByteArrayOutputStream out = new ByteArrayOutputStream(); - ppt.write(out); + ss.write(out); out.close(); - ppt = new HSLFSlideShow(new ByteArrayInputStream(out.toByteArray())); - sl = ppt.getSlides().get(0); + ss = new HSLFSlideShow(new ByteArrayInputStream(out.toByteArray())); + sl = ss.getSlides().get(0); assertEquals("expected 0 shaped in " + file, 0, sl.getShapes().size()); } @@ -413,12 +410,12 @@ public final class TestShapes { @Test public void shapeId() { - HSLFSlideShow ppt = new HSLFSlideShow(); - HSLFSlide slide = ppt.createSlide(); + HSLFSlideShow ss = new HSLFSlideShow(); + HSLFSlide slide = ss.createSlide(); HSLFShape shape = null; //EscherDgg is a document-level record which keeps track of the drawing groups - EscherDggRecord dgg = ppt.getDocumentRecord().getPPDrawingGroup().getEscherDggRecord(); + EscherDggRecord dgg = ss.getDocumentRecord().getPPDrawingGroup().getEscherDggRecord(); EscherDgRecord dg = slide.getSheetContainer().getPPDrawing().getEscherDgRecord(); int dggShapesUsed = dgg.getNumShapesSaved(); //total number of shapes in the ppt @@ -463,8 +460,8 @@ public final class TestShapes { @Test public void lineColor() throws IOException { - HSLFSlideShow ppt = new HSLFSlideShow(_slTests.openResourceAsStream("51731.ppt")); - List shape = ppt.getSlides().get(0).getShapes(); + HSLFSlideShow ss = new HSLFSlideShow(_slTests.openResourceAsStream("51731.ppt")); + List shape = ss.getSlides().get(0).getShapes(); assertEquals(4, shape.size()); diff --git a/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestHSLFSlideShowFactory.java b/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestHSLFSlideShowFactory.java new file mode 100644 index 000000000..9c305ef6b --- /dev/null +++ b/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestHSLFSlideShowFactory.java @@ -0,0 +1,28 @@ +/* ==================================================================== + 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.hslf.usermodel; + +import org.apache.poi.sl.usermodel.BaseTestSlideShowFactory; +import org.junit.Test; + +public final class TestHSLFSlideShowFactory extends BaseTestSlideShowFactory { + @Test + public void testFactory() throws Exception { + testFactory("pictures.ppt", "Password_Protected-hello.ppt", "hello"); + } +} diff --git a/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestPictures.java b/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestPictures.java index d45f18222..3afcfe596 100644 --- a/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestPictures.java +++ b/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestPictures.java @@ -35,6 +35,7 @@ import org.apache.poi.hslf.blip.PICT; import org.apache.poi.hslf.blip.PNG; import org.apache.poi.hslf.blip.WMF; import org.apache.poi.sl.usermodel.PictureData.PictureType; +import org.apache.poi.util.Units; import org.junit.Ignore; import org.junit.Test; @@ -46,8 +47,6 @@ import org.junit.Test; public final class TestPictures { private static POIDataSamples slTests = POIDataSamples.getSlideShowInstance(); - //protected File cwd; - /** * Test read/write Macintosh PICT */ @@ -64,9 +63,9 @@ public final class TestPictures { assertEquals(expWidth, nDim.getWidth(), 0); assertEquals(expHeight, nDim.getHeight(), 0); - Dimension dim = data.getImageDimension(); - assertEquals(expWidth, dim.getWidth(), 0); - assertEquals(expHeight, dim.getHeight(), 0); + Dimension dim = data.getImageDimensionInPixels(); + assertEquals(Units.pointsToPixel(expWidth), dim.getWidth(), 0); + assertEquals(Units.pointsToPixel(expHeight), dim.getHeight(), 0); HSLFPictureShape pict = new HSLFPictureShape(data); assertEquals(data.getIndex(), pict.getPictureIndex()); @@ -127,9 +126,9 @@ public final class TestPictures { assertEquals(expWidth, nDim.getWidth(), 0); assertEquals(expHeight, nDim.getHeight(), 0); - Dimension dim = data.getImageDimension(); - assertEquals(expWidth, dim.getWidth(), 0); - assertEquals(expHeight, dim.getHeight(), 0); + Dimension dim = data.getImageDimensionInPixels(); + assertEquals(Units.pointsToPixel(expWidth), dim.getWidth(), 0); + assertEquals(Units.pointsToPixel(expHeight), dim.getHeight(), 0); HSLFPictureShape pict = new HSLFPictureShape(data); assertEquals(data.getIndex(), pict.getPictureIndex()); @@ -189,9 +188,9 @@ public final class TestPictures { assertEquals(expWidth, nDim.getWidth(), 0); assertEquals(expHeight, nDim.getHeight(), 0); - Dimension dim = data.getImageDimension(); - assertEquals(expWidth, dim.getWidth(), 0); - assertEquals(expHeight, dim.getHeight(), 0); + Dimension dim = data.getImageDimensionInPixels(); + assertEquals(Units.pointsToPixel(expWidth), dim.getWidth(), 0); + assertEquals(Units.pointsToPixel(expHeight), dim.getHeight(), 0); HSLFPictureShape pict = new HSLFPictureShape(data); assertEquals(data.getIndex(), pict.getPictureIndex()); diff --git a/src/testcases/org/apache/poi/sl/draw/geom/TestPresetGeometries.java b/src/testcases/org/apache/poi/sl/draw/geom/TestPresetGeometries.java index 61bd850b6..59dd694da 100644 --- a/src/testcases/org/apache/poi/sl/draw/geom/TestPresetGeometries.java +++ b/src/testcases/org/apache/poi/sl/draw/geom/TestPresetGeometries.java @@ -22,19 +22,14 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; +import java.awt.Rectangle; import java.awt.geom.GeneralPath; -import java.awt.geom.Rectangle2D; import java.net.URL; import java.util.Enumeration; import java.util.Map; import org.junit.Test; -/** - * Date: 10/24/11 - * - * @author Yegor Kozlov - */ public class TestPresetGeometries { @Test public void testRead(){ @@ -43,8 +38,8 @@ public class TestPresetGeometries { for(String name : shapes.keySet()) { CustomGeometry geom = shapes.get(name); - Context ctx = new Context(geom, new Rectangle2D.Double(0, 0, 100, 100), new IAdjustableShape() { - public Guide getAdjustValue(String name) { + Context ctx = new Context(geom, new Rectangle(0, 0, 100, 100), new IAdjustableShape() { + public Guide getAdjustValue(String presetName) { return null; } }); diff --git a/src/testcases/org/apache/poi/sl/usermodel/BaseTestSlideShowFactory.java b/src/testcases/org/apache/poi/sl/usermodel/BaseTestSlideShowFactory.java new file mode 100644 index 000000000..ab8c16825 --- /dev/null +++ b/src/testcases/org/apache/poi/sl/usermodel/BaseTestSlideShowFactory.java @@ -0,0 +1,73 @@ +/* ==================================================================== + 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 static org.junit.Assert.assertNotNull; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; + +import org.apache.poi.POIDataSamples; +import org.apache.poi.poifs.filesystem.NPOIFSFileSystem; + +public class BaseTestSlideShowFactory { + private static POIDataSamples _slTests = POIDataSamples.getSlideShowInstance(); + + public void testFactory(String file, String protectedFile, String password) + throws Exception { + SlideShow ss; + // from file + ss = SlideShowFactory.create(fromFile(file)); + assertNotNull(ss); + // from stream + ss = SlideShowFactory.create(fromStream(file)); + assertNotNull(ss); + // from NPOIFS + if (!file.contains("pptx")) { + NPOIFSFileSystem npoifs = new NPOIFSFileSystem(fromFile(file)); + ss = SlideShowFactory.create(npoifs); + assertNotNull(ss); + npoifs.close(); + } + // from protected file + ss = SlideShowFactory.create(fromFile(protectedFile), password); + assertNotNull(ss); + // from protected stream + ss = SlideShowFactory.create(fromStream(protectedFile), password); + assertNotNull(ss); + // from protected NPOIFS + NPOIFSFileSystem npoifs = new NPOIFSFileSystem(fromFile(protectedFile)); + ss = SlideShowFactory.create(npoifs, password); + assertNotNull(ss); + npoifs.close(); + } + + private static File fromFile(String file) { + return (file.contains("/") || file.contains("\\")) + ? new File(file) + : _slTests.getFile(file); + } + + private static InputStream fromStream(String file) throws IOException { + return (file.contains("/") || file.contains("\\")) + ? new FileInputStream(file) + : _slTests.openResourceAsStream(file); + } +}