- #58216 - provide picture-shape resize that maintains the aspect ratio

- moved SlideShowFactory to Common SL
- changed get/setAnchor to Rectangle instead of Rectangle2D
- Fixed some Common SL generic definitions
- picture dimensions are now in points and an additional method exists for pixels

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1704206 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Andreas Beeker 2015-09-21 00:09:45 +00:00
parent d61ea07e26
commit dec09d2713
49 changed files with 1193 additions and 269 deletions

View File

@ -20,7 +20,7 @@
package org.apache.poi.xslf.usermodel; package org.apache.poi.xslf.usermodel;
import java.awt.Color; import java.awt.Color;
import java.awt.geom.Rectangle2D; import java.awt.Rectangle;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
@ -40,7 +40,7 @@ public class Tutorial4 {
XSLFSlide slide = ppt.createSlide(); XSLFSlide slide = ppt.createSlide();
XSLFTable tbl = slide.createTable(); 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 numColumns = 3;
int numRows = 5; int numRows = 5;

View File

@ -29,14 +29,13 @@ import java.io.IOException;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; 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.draw.Drawable;
import org.apache.poi.sl.usermodel.PictureData; import org.apache.poi.sl.usermodel.PictureData;
import org.apache.poi.sl.usermodel.Shape; import org.apache.poi.sl.usermodel.Shape;
import org.apache.poi.sl.usermodel.ShapeContainer; import org.apache.poi.sl.usermodel.ShapeContainer;
import org.apache.poi.sl.usermodel.Slide; import org.apache.poi.sl.usermodel.Slide;
import org.apache.poi.sl.usermodel.SlideShow; 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.TextParagraph;
import org.apache.poi.sl.usermodel.TextRun; import org.apache.poi.sl.usermodel.TextRun;
import org.apache.poi.sl.usermodel.TextShape; import org.apache.poi.sl.usermodel.TextShape;
@ -55,12 +54,7 @@ public abstract class SlideShowHandler extends POIFSFileHandler {
readContent(ss); readContent(ss);
// read in the writen file // read in the writen file
SlideShow<?,?> read; SlideShow<?,?> read = SlideShowFactory.create(new ByteArrayInputStream(out.toByteArray()));
try {
read = SlideShowFactory.create(new ByteArrayInputStream(out.toByteArray()));
} catch (InvalidFormatException e) {
throw new IllegalStateException(e);
}
assertNotNull(read); assertNotNull(read);
readContent(read); readContent(read);

View File

@ -20,6 +20,7 @@ package org.apache.poi.sl.draw;
import java.awt.Dimension; import java.awt.Dimension;
import java.awt.Graphics2D; import java.awt.Graphics2D;
import java.awt.Paint; import java.awt.Paint;
import java.awt.Rectangle;
import java.awt.geom.Rectangle2D; import java.awt.geom.Rectangle2D;
import org.apache.poi.sl.usermodel.Background; import org.apache.poi.sl.usermodel.Background;
@ -35,12 +36,12 @@ public class DrawBackground extends DrawShape {
@SuppressWarnings("rawtypes") @SuppressWarnings("rawtypes")
public void draw(Graphics2D graphics) { public void draw(Graphics2D graphics) {
Dimension pg = shape.getSheet().getSlideShow().getPageSize(); 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(){ PlaceableShape<?,?> ps = new PlaceableShape(){
public ShapeContainer<?,?> getParent() { return null; } public ShapeContainer<?,?> getParent() { return null; }
public Rectangle2D getAnchor() { return anchor; } public Rectangle getAnchor() { return anchor; }
public void setAnchor(Rectangle2D anchor) {} public void setAnchor(Rectangle newAnchor) {}
public double getRotation() { return 0; } public double getRotation() { return 0; }
public void setRotation(double theta) {} public void setRotation(double theta) {}
public void setFlipHorizontal(boolean flip) {} public void setFlipHorizontal(boolean flip) {}

View File

@ -17,13 +17,16 @@
package org.apache.poi.sl.draw; package org.apache.poi.sl.draw;
import java.awt.Dimension;
import java.awt.Graphics2D; import java.awt.Graphics2D;
import java.awt.Insets; import java.awt.Insets;
import java.awt.Rectangle;
import java.awt.geom.Rectangle2D; import java.awt.geom.Rectangle2D;
import java.io.IOException; import java.io.IOException;
import org.apache.poi.sl.usermodel.PictureData; import org.apache.poi.sl.usermodel.PictureData;
import org.apache.poi.sl.usermodel.PictureShape; import org.apache.poi.sl.usermodel.PictureShape;
import org.apache.poi.sl.usermodel.RectAlign;
public class DrawPictureShape extends DrawSimpleShape { public class DrawPictureShape extends DrawSimpleShape {
@ -56,4 +59,117 @@ public class DrawPictureShape extends DrawSimpleShape {
protected PictureShape<?,?> getShape() { protected PictureShape<?,?> getShape() {
return (PictureShape<?,?>)shape; 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));
}
} }

View File

@ -25,10 +25,8 @@ import java.awt.geom.AffineTransform;
import java.awt.geom.Ellipse2D; import java.awt.geom.Ellipse2D;
import java.awt.geom.GeneralPath; import java.awt.geom.GeneralPath;
import java.awt.geom.Rectangle2D; import java.awt.geom.Rectangle2D;
import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.nio.charset.Charset;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
@ -145,7 +143,7 @@ public class DrawSimpleShape extends DrawShape {
double alpha = Math.atan(anchor.getHeight() / anchor.getWidth()); double alpha = Math.atan(anchor.getHeight() / anchor.getWidth());
AffineTransform at = new AffineTransform(); AffineTransform at = new AffineTransform();
java.awt.Shape shape = null; java.awt.Shape tailShape = null;
Path p = null; Path p = null;
Rectangle2D bounds; Rectangle2D bounds;
final double scaleY = Math.pow(2, tailWidth.ordinal()+1); final double scaleY = Math.pow(2, tailWidth.ordinal()+1);
@ -153,8 +151,8 @@ public class DrawSimpleShape extends DrawShape {
switch (deco.getTailShape()) { switch (deco.getTailShape()) {
case OVAL: case OVAL:
p = new Path(); p = new Path();
shape = new Ellipse2D.Double(0, 0, lineWidth * scaleX, lineWidth * scaleY); tailShape = new Ellipse2D.Double(0, 0, lineWidth * scaleX, lineWidth * scaleY);
bounds = shape.getBounds2D(); bounds = tailShape.getBounds2D();
at.translate(x2 - bounds.getWidth() / 2, y2 - bounds.getHeight() / 2); at.translate(x2 - bounds.getWidth() / 2, y2 - bounds.getHeight() / 2);
at.rotate(alpha, bounds.getX() + bounds.getWidth() / 2, bounds.getY() + bounds.getHeight() / 2); at.rotate(alpha, bounds.getX() + bounds.getWidth() / 2, bounds.getY() + bounds.getHeight() / 2);
break; break;
@ -165,7 +163,7 @@ public class DrawSimpleShape extends DrawShape {
arrow.moveTo((float) (-lineWidth * scaleX), (float) (-lineWidth * scaleY / 2)); arrow.moveTo((float) (-lineWidth * scaleX), (float) (-lineWidth * scaleY / 2));
arrow.lineTo(0, 0); arrow.lineTo(0, 0);
arrow.lineTo((float) (-lineWidth * scaleX), (float) (lineWidth * scaleY / 2)); arrow.lineTo((float) (-lineWidth * scaleX), (float) (lineWidth * scaleY / 2));
shape = arrow; tailShape = arrow;
at.translate(x2, y2); at.translate(x2, y2);
at.rotate(alpha); at.rotate(alpha);
break; break;
@ -176,7 +174,7 @@ public class DrawSimpleShape extends DrawShape {
triangle.lineTo(0, 0); triangle.lineTo(0, 0);
triangle.lineTo((float) (-lineWidth * scaleX), (float) (lineWidth * scaleY / 2)); triangle.lineTo((float) (-lineWidth * scaleX), (float) (lineWidth * scaleY / 2));
triangle.closePath(); triangle.closePath();
shape = triangle; tailShape = triangle;
at.translate(x2, y2); at.translate(x2, y2);
at.rotate(alpha); at.rotate(alpha);
break; break;
@ -184,10 +182,10 @@ public class DrawSimpleShape extends DrawShape {
break; break;
} }
if (shape != null) { if (tailShape != null) {
shape = at.createTransformedShape(shape); 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) { 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()); double alpha = Math.atan(anchor.getHeight() / anchor.getWidth());
AffineTransform at = new AffineTransform(); AffineTransform at = new AffineTransform();
java.awt.Shape shape = null; java.awt.Shape headShape = null;
Path p = null; Path p = null;
Rectangle2D bounds; Rectangle2D bounds;
final double scaleY = Math.pow(2, headWidth.ordinal()+1); final double scaleY = Math.pow(2, headWidth.ordinal()+1);
@ -211,8 +209,8 @@ public class DrawSimpleShape extends DrawShape {
switch (deco.getHeadShape()) { switch (deco.getHeadShape()) {
case OVAL: case OVAL:
p = new Path(); p = new Path();
shape = new Ellipse2D.Double(0, 0, lineWidth * scaleX, lineWidth * scaleY); headShape = new Ellipse2D.Double(0, 0, lineWidth * scaleX, lineWidth * scaleY);
bounds = shape.getBounds2D(); bounds = headShape.getBounds2D();
at.translate(x1 - bounds.getWidth() / 2, y1 - bounds.getHeight() / 2); at.translate(x1 - bounds.getWidth() / 2, y1 - bounds.getHeight() / 2);
at.rotate(alpha, bounds.getX() + bounds.getWidth() / 2, bounds.getY() + bounds.getHeight() / 2); at.rotate(alpha, bounds.getX() + bounds.getWidth() / 2, bounds.getY() + bounds.getHeight() / 2);
break; break;
@ -223,7 +221,7 @@ public class DrawSimpleShape extends DrawShape {
arrow.moveTo((float) (lineWidth * scaleX), (float) (-lineWidth * scaleY / 2)); arrow.moveTo((float) (lineWidth * scaleX), (float) (-lineWidth * scaleY / 2));
arrow.lineTo(0, 0); arrow.lineTo(0, 0);
arrow.lineTo((float) (lineWidth * scaleX), (float) (lineWidth * scaleY / 2)); arrow.lineTo((float) (lineWidth * scaleX), (float) (lineWidth * scaleY / 2));
shape = arrow; headShape = arrow;
at.translate(x1, y1); at.translate(x1, y1);
at.rotate(alpha); at.rotate(alpha);
break; break;
@ -234,7 +232,7 @@ public class DrawSimpleShape extends DrawShape {
triangle.lineTo(0, 0); triangle.lineTo(0, 0);
triangle.lineTo((float) (lineWidth * scaleX), (float) (lineWidth * scaleY / 2)); triangle.lineTo((float) (lineWidth * scaleX), (float) (lineWidth * scaleY / 2));
triangle.closePath(); triangle.closePath();
shape = triangle; headShape = triangle;
at.translate(x1, y1); at.translate(x1, y1);
at.rotate(alpha); at.rotate(alpha);
break; break;
@ -242,10 +240,10 @@ public class DrawSimpleShape extends DrawShape {
break; break;
} }
if (shape != null) { if (headShape != null) {
shape = at.createTransformedShape(shape); headShape = at.createTransformedShape(headShape);
} }
return shape == null ? null : new Outline(shape, p); return headShape == null ? null : new Outline(headShape, p);
} }
public BasicStroke getStroke() { public BasicStroke getStroke() {
@ -296,7 +294,7 @@ public class DrawSimpleShape extends DrawShape {
, Paint fill , Paint fill
, Paint line , Paint line
) { ) {
Shadow shadow = getShape().getShadow(); Shadow<?,?> shadow = getShape().getShadow();
if (shadow == null || (fill == null && line == null)) return; if (shadow == null || (fill == null && line == null)) return;
SolidPaint shadowPaint = shadow.getFillStyle(); SolidPaint shadowPaint = shadow.getFillStyle();
@ -347,7 +345,6 @@ public class DrawSimpleShape extends DrawShape {
String packageName = "org.apache.poi.sl.draw.binding"; String packageName = "org.apache.poi.sl.draw.binding";
InputStream presetIS = Drawable.class.getResourceAsStream("presetShapeDefinitions.xml"); InputStream presetIS = Drawable.class.getResourceAsStream("presetShapeDefinitions.xml");
Reader xml = new InputStreamReader( presetIS, Charset.forName("UTF-8") );
// StAX: // StAX:
EventFilter startElementFilter = new EventFilter() { EventFilter startElementFilter = new EventFilter() {
@ -359,7 +356,7 @@ public class DrawSimpleShape extends DrawShape {
try { try {
XMLInputFactory staxFactory = XMLInputFactory.newInstance(); XMLInputFactory staxFactory = XMLInputFactory.newInstance();
XMLEventReader staxReader = staxFactory.createXMLEventReader(xml); XMLEventReader staxReader = staxFactory.createXMLEventReader(presetIS);
XMLEventReader staxFiltRd = staxFactory.createFilteredReader(staxReader, startElementFilter); XMLEventReader staxFiltRd = staxFactory.createFilteredReader(staxReader, startElementFilter);
// Ignore StartElement: // Ignore StartElement:
staxFiltRd.nextEvent(); staxFiltRd.nextEvent();
@ -378,6 +375,12 @@ public class DrawSimpleShape extends DrawShape {
} }
} catch (Exception e) { } catch (Exception e) {
throw new RuntimeException("Unable to load preset geometries.", 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);
}
} }
} }

View File

@ -19,6 +19,7 @@ package org.apache.poi.sl.draw;
import java.awt.Graphics2D; import java.awt.Graphics2D;
import java.awt.Paint; import java.awt.Paint;
import java.awt.Rectangle;
import java.awt.font.FontRenderContext; import java.awt.font.FontRenderContext;
import java.awt.font.LineBreakMeasurer; import java.awt.font.LineBreakMeasurer;
import java.awt.font.TextAttribute; import java.awt.font.TextAttribute;
@ -416,8 +417,8 @@ public class DrawTextParagraph implements Drawable {
private PlaceableShape<?,?> getParagraphShape() { private PlaceableShape<?,?> getParagraphShape() {
PlaceableShape<?,?> ps = new PlaceableShape(){ PlaceableShape<?,?> ps = new PlaceableShape(){
public ShapeContainer<?,?> getParent() { return null; } public ShapeContainer<?,?> getParent() { return null; }
public Rectangle2D getAnchor() { return paragraph.getParentShape().getAnchor(); } public Rectangle getAnchor() { return paragraph.getParentShape().getAnchor(); }
public void setAnchor(Rectangle2D anchor) {} public void setAnchor(Rectangle anchor) {}
public double getRotation() { return 0; } public double getRotation() { return 0; }
public void setRotation(double theta) {} public void setRotation(double theta) {}
public void setFlipHorizontal(boolean flip) {} public void setFlipHorizontal(boolean flip) {}

View File

@ -17,7 +17,7 @@
package org.apache.poi.sl.usermodel; package org.apache.poi.sl.usermodel;
import java.awt.geom.Rectangle2D; import java.awt.Rectangle;
public interface GroupShape< public interface GroupShape<
S extends Shape<S,P>, S extends Shape<S,P>,
@ -30,7 +30,7 @@ public interface GroupShape<
* *
* @return the coordinate space of this group * @return the coordinate space of this group
*/ */
Rectangle2D getInteriorAnchor(); Rectangle getInteriorAnchor();
/** /**
* Sets the coordinate space of this group. All children are constrained * 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 * @param anchor the coordinate space of this group
*/ */
void setInteriorAnchor(Rectangle2D anchor); void setInteriorAnchor(Rectangle anchor);
} }

View File

@ -106,10 +106,16 @@ public interface PictureData {
byte[] getChecksum(); byte[] getChecksum();
/** /**
* Return the original image dimensions * Return the original image dimensions in points
* (for formats supported by BufferedImage). * (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(); Dimension getImageDimension();
/**
* Return the original image dimensions in pixels
* @see PictureData#getImageDimension()
*/
Dimension getImageDimensionInPixels();
} }

View File

@ -17,7 +17,7 @@
package org.apache.poi.sl.usermodel; package org.apache.poi.sl.usermodel;
import java.awt.geom.Rectangle2D; import java.awt.Rectangle;
public interface PlaceableShape< public interface PlaceableShape<
S extends Shape<S,P>, S extends Shape<S,P>,
@ -29,13 +29,13 @@ public interface PlaceableShape<
* @return the position of this shape within the drawing canvas. * @return the position of this shape within the drawing canvas.
* The coordinates are expressed in points * The coordinates are expressed in points
*/ */
Rectangle2D getAnchor(); Rectangle getAnchor();
/** /**
* @param anchor the position of this shape within the drawing canvas. * @param anchor the position of this shape within the drawing canvas.
* The coordinates are expressed in points * The coordinates are expressed in points
*/ */
void setAnchor(Rectangle2D anchor); void setAnchor(Rectangle anchor);
/** /**
* Rotation angle in degrees * Rotation angle in degrees

View File

@ -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;
}
}
/* ************************************************************************** */

View File

@ -21,8 +21,11 @@ import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint;
public interface Shadow { public interface Shadow<
SimpleShape getShadowParent(); S extends Shape<S,P>,
P extends TextParagraph<S,P,?>
> {
SimpleShape<S,P> getShadowParent();
/** /**
* @return the offset of this shadow in points * @return the offset of this shadow in points

View File

@ -17,6 +17,7 @@
package org.apache.poi.sl.usermodel; package org.apache.poi.sl.usermodel;
import java.awt.Rectangle;
public interface Shape< public interface Shape<
S extends Shape<S,P>, S extends Shape<S,P>,
@ -29,4 +30,12 @@ public interface Shape<
* @return the sheet this shape belongs to * @return the sheet this shape belongs to
*/ */
Sheet<S,P> getSheet(); Sheet<S,P> 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();
} }

View File

@ -35,5 +35,5 @@ public interface SimpleShape<
boolean isPlaceholder(); boolean isPlaceholder();
Shadow getShadow(); Shadow<S,P> getShadow();
} }

View File

@ -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.
*
* <p>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}.</p>
*
* <p>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.
* <p>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}.</p>
*
* <p>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.</p>
*
* @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.
* <p>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
* <p>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
* <p>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]
);
}
}

View File

@ -19,7 +19,7 @@ package org.apache.poi.xslf.usermodel;
import java.awt.Color; import java.awt.Color;
import java.awt.Dimension; 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.draw.DrawPaint;
import org.apache.poi.sl.usermodel.Background; import org.apache.poi.sl.usermodel.Background;
@ -43,9 +43,9 @@ public class XSLFBackground extends XSLFSimpleShape
} }
@Override @Override
public Rectangle2D getAnchor(){ public Rectangle getAnchor(){
Dimension pg = getSheet().getSlideShow().getPageSize(); 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 @Override

View File

@ -19,6 +19,7 @@
package org.apache.poi.xslf.usermodel; package org.apache.poi.xslf.usermodel;
import java.awt.Rectangle;
import java.awt.geom.AffineTransform; import java.awt.geom.AffineTransform;
import java.awt.geom.GeneralPath; import java.awt.geom.GeneralPath;
import java.awt.geom.PathIterator; import java.awt.geom.PathIterator;
@ -60,7 +61,7 @@ public class XSLFFreeformShape extends XSLFAutoShape
public int setPath(GeneralPath path) { public int setPath(GeneralPath path) {
CTPath2D ctPath = CTPath2D.Factory.newInstance(); CTPath2D ctPath = CTPath2D.Factory.newInstance();
Rectangle2D bounds = path.getBounds2D(); Rectangle bounds = path.getBounds();
int x0 = Units.toEMU(bounds.getX()); int x0 = Units.toEMU(bounds.getX());
int y0 = Units.toEMU(bounds.getY()); int y0 = Units.toEMU(bounds.getY());
PathIterator it = path.getPathIterator(new AffineTransform()); PathIterator it = path.getPathIterator(new AffineTransform());

View File

@ -19,7 +19,7 @@
package org.apache.poi.xslf.usermodel; package org.apache.poi.xslf.usermodel;
import java.awt.geom.Rectangle2D; import java.awt.Rectangle;
import javax.xml.namespace.QName; import javax.xml.namespace.QName;
@ -53,20 +53,19 @@ public class XSLFGraphicFrame extends XSLFShape {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
public Rectangle2D getAnchor(){ @Override
public Rectangle getAnchor(){
CTTransform2D xfrm = ((CTGraphicalObjectFrame)getXmlObject()).getXfrm(); CTTransform2D xfrm = ((CTGraphicalObjectFrame)getXmlObject()).getXfrm();
CTPoint2D off = xfrm.getOff(); CTPoint2D off = xfrm.getOff();
long x = off.getX(); int x = (int)Units.toPoints(off.getX());
long y = off.getY(); int y = (int)Units.toPoints(off.getY());
CTPositiveSize2D ext = xfrm.getExt(); CTPositiveSize2D ext = xfrm.getExt();
long cx = ext.getCx(); int cx = (int)Units.toPoints(ext.getCx());
long cy = ext.getCy(); int cy = (int)Units.toPoints(ext.getCy());
return new Rectangle2D.Double( return new Rectangle(x, y, cx, cy);
Units.toPoints(x), Units.toPoints(y),
Units.toPoints(cx), Units.toPoints(cy));
} }
public void setAnchor(Rectangle2D anchor){ public void setAnchor(Rectangle anchor){
CTTransform2D xfrm = ((CTGraphicalObjectFrame)getXmlObject()).getXfrm(); CTTransform2D xfrm = ((CTGraphicalObjectFrame)getXmlObject()).getXfrm();
CTPoint2D off = xfrm.isSetOff() ? xfrm.getOff() : xfrm.addNewOff(); CTPoint2D off = xfrm.isSetOff() ? xfrm.getOff() : xfrm.addNewOff();
long x = Units.toEMU(anchor.getX()); long x = Units.toEMU(anchor.getX());

View File

@ -19,7 +19,7 @@
package org.apache.poi.xslf.usermodel; package org.apache.poi.xslf.usermodel;
import java.awt.geom.Rectangle2D; import java.awt.Rectangle;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; 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.PackagePart;
import org.apache.poi.openxml4j.opc.PackageRelationship; import org.apache.poi.openxml4j.opc.PackageRelationship;
import org.apache.poi.openxml4j.opc.TargetMode; 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.GroupShape;
import org.apache.poi.sl.usermodel.PictureData; import org.apache.poi.sl.usermodel.PictureData;
import org.apache.poi.util.Beta; import org.apache.poi.util.Beta;
@ -78,21 +79,19 @@ implements XSLFShapeContainer, GroupShape<XSLFShape,XSLFTextParagraph> {
} }
@Override @Override
public Rectangle2D getAnchor(){ public Rectangle getAnchor(){
CTGroupTransform2D xfrm = getXfrm(); CTGroupTransform2D xfrm = getXfrm();
CTPoint2D off = xfrm.getOff(); CTPoint2D off = xfrm.getOff();
long x = off.getX(); int x = (int)Units.toPoints(off.getX());
long y = off.getY(); int y = (int)Units.toPoints(off.getY());
CTPositiveSize2D ext = xfrm.getExt(); CTPositiveSize2D ext = xfrm.getExt();
long cx = ext.getCx(); int cx = (int)Units.toPoints(ext.getCx());
long cy = ext.getCy(); int cy = (int)Units.toPoints(ext.getCy());
return new Rectangle2D.Double( return new Rectangle(x,y,cx,cy);
Units.toPoints(x), Units.toPoints(y),
Units.toPoints(cx), Units.toPoints(cy));
} }
@Override @Override
public void setAnchor(Rectangle2D anchor){ public void setAnchor(Rectangle anchor){
CTGroupTransform2D xfrm = getSafeXfrm(); CTGroupTransform2D xfrm = getSafeXfrm();
CTPoint2D off = xfrm.isSetOff() ? xfrm.getOff() : xfrm.addNewOff(); CTPoint2D off = xfrm.isSetOff() ? xfrm.getOff() : xfrm.addNewOff();
long x = Units.toEMU(anchor.getX()); long x = Units.toEMU(anchor.getX());
@ -112,17 +111,15 @@ implements XSLFShapeContainer, GroupShape<XSLFShape,XSLFTextParagraph> {
* used for calculations of grouping, scaling, and rotation * used for calculations of grouping, scaling, and rotation
* behavior of shapes placed within a group. * behavior of shapes placed within a group.
*/ */
public Rectangle2D getInteriorAnchor(){ public Rectangle getInteriorAnchor(){
CTGroupTransform2D xfrm = getXfrm(); CTGroupTransform2D xfrm = getXfrm();
CTPoint2D off = xfrm.getChOff(); CTPoint2D off = xfrm.getChOff();
long x = off.getX(); int x = (int)Units.toPoints(off.getX());
long y = off.getY(); int y = (int)Units.toPoints(off.getY());
CTPositiveSize2D ext = xfrm.getChExt(); CTPositiveSize2D ext = xfrm.getChExt();
long cx = ext.getCx(); int cx = (int)Units.toPoints(ext.getCx());
long cy = ext.getCy(); int cy = (int)Units.toPoints(ext.getCy());
return new Rectangle2D.Double( return new Rectangle(x, y, cx, cy);
Units.toPoints(x), Units.toPoints(y),
Units.toPoints(cx), Units.toPoints(cy));
} }
/** /**
@ -131,7 +128,7 @@ implements XSLFShapeContainer, GroupShape<XSLFShape,XSLFTextParagraph> {
* used for calculations of grouping, scaling, and rotation * used for calculations of grouping, scaling, and rotation
* behavior of shapes placed within a group. * behavior of shapes placed within a group.
*/ */
public void setInteriorAnchor(Rectangle2D anchor) { public void setInteriorAnchor(Rectangle anchor) {
CTGroupTransform2D xfrm = getSafeXfrm(); CTGroupTransform2D xfrm = getSafeXfrm();
CTPoint2D off = xfrm.isSetChOff() ? xfrm.getChOff() : xfrm.addNewChOff(); CTPoint2D off = xfrm.isSetChOff() ? xfrm.getChOff() : xfrm.addNewChOff();
long x = Units.toEMU(anchor.getX()); long x = Units.toEMU(anchor.getX());
@ -250,7 +247,7 @@ implements XSLFShapeContainer, GroupShape<XSLFShape,XSLFTextParagraph> {
pic.getPartName(), TargetMode.INTERNAL, XSLFRelation.IMAGES.getRelation()); pic.getPartName(), TargetMode.INTERNAL, XSLFRelation.IMAGES.getRelation());
XSLFPictureShape sh = getDrawing().createPicture(rel.getId()); XSLFPictureShape sh = getDrawing().createPicture(rel.getId());
sh.resize(); new DrawPictureShape(sh).resize();
_shapes.add(sh); _shapes.add(sh);
sh.setParent(this); sh.setParent(this);
return sh; return sh;

View File

@ -42,6 +42,7 @@ import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.LittleEndianConsts; import org.apache.poi.util.LittleEndianConsts;
import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger; import org.apache.poi.util.POILogger;
import org.apache.poi.util.Units;
/** /**
* Instantiates sub-classes of POIXMLDocumentPart depending on their relationship type * Instantiates sub-classes of POIXMLDocumentPart depending on their relationship type
@ -134,6 +135,15 @@ public final class XSLFPictureData extends POIXMLDocumentPart implements Picture
return _origSize; 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 * Determine and cache image properties
*/ */
@ -155,14 +165,19 @@ public final class XSLFPictureData extends POIXMLDocumentPart implements Picture
_origSize = new PICT.NativeHeader(data, 0).getSize(); _origSize = new PICT.NativeHeader(data, 0).getSize();
break; break;
default: default:
BufferedImage img = null;
try { try {
BufferedImage img = ImageIO.read(new ByteArrayInputStream(data)); img = ImageIO.read(new ByteArrayInputStream(data));
_origSize = (img == null) ? new Dimension() : new Dimension(img.getWidth(), img.getHeight());
} catch (IOException e) { } catch (IOException e) {
logger.log(POILogger.WARN, "Can't determine image dimensions", 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; break;
} }
} }

View File

@ -19,10 +19,9 @@
package org.apache.poi.xslf.usermodel; package org.apache.poi.xslf.usermodel;
import java.awt.Dimension;
import java.awt.Insets; import java.awt.Insets;
import java.awt.Rectangle;
import java.net.URI; import java.net.URI;
import javax.xml.namespace.QName; import javax.xml.namespace.QName;
import org.apache.poi.POIXMLException; import org.apache.poi.POIXMLException;
@ -83,24 +82,6 @@ public class XSLFPictureShape extends XSLFSimpleShape
return ct; 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 * Is this an internal picture (image data included within

View File

@ -18,7 +18,7 @@
package org.apache.poi.xslf.usermodel; package org.apache.poi.xslf.usermodel;
import java.awt.Color; 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.draw.DrawPaint;
import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint; import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint;
@ -32,7 +32,7 @@ import org.openxmlformats.schemas.drawingml.x2006.main.CTSchemeColor;
* *
* @author Yegor Kozlov * @author Yegor Kozlov
*/ */
public class XSLFShadow extends XSLFShape implements Shadow { public class XSLFShadow extends XSLFShape implements Shadow<XSLFShape,XSLFTextParagraph> {
private XSLFSimpleShape _parent; private XSLFSimpleShape _parent;
@ -47,11 +47,12 @@ public class XSLFShadow extends XSLFShape implements Shadow {
return _parent; return _parent;
} }
public Rectangle2D getAnchor(){ @Override
public Rectangle getAnchor(){
return _parent.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"); throw new IllegalStateException("You can't set anchor of a shadow");
} }

View File

@ -36,6 +36,7 @@ import org.apache.poi.openxml4j.opc.PackagePartName;
import org.apache.poi.openxml4j.opc.PackageRelationship; import org.apache.poi.openxml4j.opc.PackageRelationship;
import org.apache.poi.openxml4j.opc.TargetMode; import org.apache.poi.openxml4j.opc.TargetMode;
import org.apache.poi.sl.draw.DrawFactory; 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.draw.Drawable;
import org.apache.poi.sl.usermodel.PictureData; import org.apache.poi.sl.usermodel.PictureData;
import org.apache.poi.sl.usermodel.Sheet; import org.apache.poi.sl.usermodel.Sheet;
@ -213,7 +214,7 @@ implements XSLFShapeContainer, Sheet<XSLFShape,XSLFTextParagraph> {
addRelation(rel.getId(), new XSLFPictureData(pic, rel)); addRelation(rel.getId(), new XSLFPictureData(pic, rel));
XSLFPictureShape sh = getDrawing().createPicture(rel.getId()); XSLFPictureShape sh = getDrawing().createPicture(rel.getId());
sh.resize(); new DrawPictureShape(sh).resize();
getShapes().add(sh); getShapes().add(sh);
sh.setParent(this); sh.setParent(this);
return sh; return sh;
@ -537,6 +538,7 @@ implements XSLFShapeContainer, Sheet<XSLFShape,XSLFTextParagraph> {
* @param packagePart package part containing the data to import * @param packagePart package part containing the data to import
* @return ID of the created relationship * @return ID of the created relationship
*/ */
@SuppressWarnings("resource")
String importBlip(String blipId, PackagePart packagePart) { String importBlip(String blipId, PackagePart packagePart) {
PackageRelationship blipRel = packagePart.getRelationship(blipId); PackageRelationship blipRel = packagePart.getRelationship(blipId);
PackagePart blipPart; PackagePart blipPart;
@ -561,6 +563,7 @@ implements XSLFShapeContainer, Sheet<XSLFShape,XSLFTextParagraph> {
/** /**
* Import a package part into this sheet. * Import a package part into this sheet.
*/ */
@SuppressWarnings("resource")
PackagePart importPart(PackageRelationship srcRel, PackagePart srcPafrt) { PackagePart importPart(PackageRelationship srcRel, PackagePart srcPafrt) {
PackagePart destPP = getPackagePart(); PackagePart destPP = getPackagePart();
PackagePartName srcPPName = srcPafrt.getPartName(); PackagePartName srcPPName = srcPafrt.getPartName();
@ -574,10 +577,11 @@ implements XSLFShapeContainer, Sheet<XSLFShape,XSLFTextParagraph> {
destPP.addRelationship(srcPPName, TargetMode.INTERNAL, srcRel.getRelationshipType()); destPP.addRelationship(srcPPName, TargetMode.INTERNAL, srcRel.getRelationshipType());
PackagePart part = pkg.createPart(srcPPName, srcPafrt.getContentType()); PackagePart part = pkg.createPart(srcPPName, srcPafrt.getContentType());
OutputStream out = part.getOutputStream();
try { try {
OutputStream out = part.getOutputStream();
InputStream is = srcPafrt.getInputStream(); InputStream is = srcPafrt.getInputStream();
IOUtils.copy(is, out); IOUtils.copy(is, out);
is.close();
out.close(); out.close();
} catch (IOException e){ } catch (IOException e){
throw new POIXMLException(e); throw new POIXMLException(e);

View File

@ -20,7 +20,7 @@
package org.apache.poi.xslf.usermodel; package org.apache.poi.xslf.usermodel;
import java.awt.Color; import java.awt.Color;
import java.awt.geom.Rectangle2D; import java.awt.Rectangle;
import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader; 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.util.Units;
import org.apache.poi.xslf.model.PropertyFetcher; import org.apache.poi.xslf.model.PropertyFetcher;
import org.apache.xmlbeans.XmlObject; 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; import org.openxmlformats.schemas.presentationml.x2006.main.CTPlaceholder;
/** /**
@ -97,23 +123,21 @@ public abstract class XSLFSimpleShape extends XSLFShape
} }
@Override @Override
public Rectangle2D getAnchor() { public Rectangle getAnchor() {
CTTransform2D xfrm = getXfrm(); CTTransform2D xfrm = getXfrm();
CTPoint2D off = xfrm.getOff(); CTPoint2D off = xfrm.getOff();
long x = off.getX(); int x = (int)Units.toPoints(off.getX());
long y = off.getY(); int y = (int)Units.toPoints(off.getY());
CTPositiveSize2D ext = xfrm.getExt(); CTPositiveSize2D ext = xfrm.getExt();
long cx = ext.getCx(); int cx = (int)Units.toPoints(ext.getCx());
long cy = ext.getCy(); int cy = (int)Units.toPoints(ext.getCy());
return new Rectangle2D.Double( return new Rectangle(x, y, cx, cy);
Units.toPoints(x), Units.toPoints(y),
Units.toPoints(cx), Units.toPoints(cy));
} }
@Override @Override
public void setAnchor(Rectangle2D anchor) { public void setAnchor(Rectangle anchor) {
CTTransform2D xfrm = getSafeXfrm(); CTTransform2D xfrm = getSafeXfrm();
CTPoint2D off = xfrm.isSetOff() ? xfrm.getOff() : xfrm.addNewOff(); CTPoint2D off = xfrm.isSetOff() ? xfrm.getOff() : xfrm.addNewOff();
long x = Units.toEMU(anchor.getX()); long x = Units.toEMU(anchor.getX());

View File

@ -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
*
* <p>Note that in order to properly release resources the
* SlideShow should be closed after use.</p>
*
* @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.
* <p>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
*
* <p>Note that in order to properly release resources the
* SlideShow should be closed after use.</p>
*
* @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);
}
}

View File

@ -19,7 +19,7 @@
package org.apache.poi.xslf.usermodel; package org.apache.poi.xslf.usermodel;
import java.awt.geom.Rectangle2D; import java.awt.Rectangle;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
@ -466,8 +466,8 @@ public abstract class XSLFTextShape extends XSLFSimpleShape
* *
* @return a <code>Rectangle2D</code> that is the bounds of this shape. * @return a <code>Rectangle2D</code> that is the bounds of this shape.
*/ */
public Rectangle2D resizeToFitText(){ public Rectangle resizeToFitText(){
Rectangle2D anchor = getAnchor(); Rectangle anchor = getAnchor();
if(anchor.getWidth() == 0.) throw new POIXMLException( if(anchor.getWidth() == 0.) throw new POIXMLException(
"Anchor of the shape was not set."); "Anchor of the shape was not set.");
double height = getTextHeight(); double height = getTextHeight();

View File

@ -31,10 +31,10 @@ import java.util.Map;
import javax.imageio.ImageIO; import javax.imageio.ImageIO;
import org.apache.poi.sl.SlideShowFactory;
import org.apache.poi.sl.draw.Drawable; import org.apache.poi.sl.draw.Drawable;
import org.apache.poi.sl.usermodel.Slide; import org.apache.poi.sl.usermodel.Slide;
import org.apache.poi.sl.usermodel.SlideShow; import org.apache.poi.sl.usermodel.SlideShow;
import org.apache.poi.sl.usermodel.SlideShowFactory;
import org.apache.poi.util.JvmBugs; import org.apache.poi.util.JvmBugs;
/** /**

View File

@ -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);
}
}
}

View File

@ -16,10 +16,12 @@
==================================================================== */ ==================================================================== */
package org.apache.poi.xslf.usermodel; 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.Dimension;
import java.awt.geom.Rectangle2D; import java.awt.Rectangle;
import org.junit.Test; import org.junit.Test;
@ -29,7 +31,7 @@ import org.junit.Test;
public class TestXSLFGroupShape { public class TestXSLFGroupShape {
@Test @Test
public void testCreateShapes() { public void testCreateShapes() throws Exception {
XMLSlideShow ppt = new XMLSlideShow(); XMLSlideShow ppt = new XMLSlideShow();
XSLFSlide slide = ppt.createSlide(); XSLFSlide slide = ppt.createSlide();
@ -38,11 +40,11 @@ public class TestXSLFGroupShape {
XSLFGroupShape group = slide.createGroup(); XSLFGroupShape group = slide.createGroup();
assertEquals(1, slide.getShapes().size()); 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); group.setInteriorAnchor(interior);
assertEquals(interior, group.getInteriorAnchor()); assertEquals(interior, group.getInteriorAnchor());
Rectangle2D anchor = new Rectangle2D.Double(0, 0, 792, 612); Rectangle anchor = new Rectangle(0, 0, 792, 612);
group.setAnchor(anchor); group.setAnchor(anchor);
assertEquals(anchor, group.getAnchor()); assertEquals(anchor, group.getAnchor());
@ -83,10 +85,12 @@ public class TestXSLFGroupShape {
group.removeShape(shape1); group.removeShape(shape1);
group.removeShape(shape4); group.removeShape(shape4);
assertTrue(group.getShapes().isEmpty()); assertTrue(group.getShapes().isEmpty());
ppt.close();
} }
@Test @Test
public void testRemoveShapes() { public void testRemoveShapes() throws Exception {
XMLSlideShow ppt = new XMLSlideShow(); XMLSlideShow ppt = new XMLSlideShow();
XSLFSlide slide = ppt.createSlide(); XSLFSlide slide = ppt.createSlide();
@ -99,5 +103,6 @@ public class TestXSLFGroupShape {
slide.removeShape(group2); slide.removeShape(group2);
slide.removeShape(group3); slide.removeShape(group3);
ppt.close();
} }
} }

View File

@ -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;
}
}

View File

@ -25,7 +25,6 @@ import static org.junit.Assert.assertTrue;
import java.awt.Color; import java.awt.Color;
import java.awt.Graphics2D; import java.awt.Graphics2D;
import java.awt.Rectangle; import java.awt.Rectangle;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.io.IOException; import java.io.IOException;
import java.util.List; import java.util.List;
@ -75,7 +74,7 @@ public class TestXSLFTextParagraph {
"of text within a shape. Properties here apply to all text " + "of text within a shape. Properties here apply to all text " +
"residing within the corresponding paragraph."); "residing within the corresponding paragraph.");
Rectangle2D anchor = new Rectangle(50, 50, 300, 200); Rectangle anchor = new Rectangle(50, 50, 300, 200);
sh.setAnchor(anchor); sh.setAnchor(anchor);
DrawTextParagraphProxy dtp = new DrawTextParagraphProxy(p); DrawTextParagraphProxy dtp = new DrawTextParagraphProxy(p);

View File

@ -26,6 +26,7 @@ import java.io.IOException;
import javax.imageio.ImageIO; import javax.imageio.ImageIO;
import org.apache.poi.hslf.usermodel.HSLFPictureData; import org.apache.poi.hslf.usermodel.HSLFPictureData;
import org.apache.poi.util.Units;
/** /**
* Represents a bitmap picture data: JPEG or PNG. * Represents a bitmap picture data: JPEG or PNG.
@ -55,10 +56,14 @@ public abstract class Bitmap extends HSLFPictureData {
setRawData(out.toByteArray()); setRawData(out.toByteArray());
} }
@Override
public Dimension getImageDimension() { public Dimension getImageDimension() {
try { try {
BufferedImage bi = ImageIO.read(new ByteArrayInputStream(getData())); 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) { } catch (IOException e) {
return new Dimension(200,200); return new Dimension(200,200);
} }

View File

@ -126,7 +126,7 @@ public abstract class Metafile extends HSLFPictureData {
return out.toByteArray(); return out.toByteArray();
} }
@Override
public Dimension getImageDimension() { public Dimension getImageDimension() {
int prefixLen = 16*uidInstanceCount; int prefixLen = 16*uidInstanceCount;
Header header = new Header(); Header header = new Header();

View File

@ -42,7 +42,6 @@ import java.awt.geom.Arc2D;
import java.awt.geom.Ellipse2D; import java.awt.geom.Ellipse2D;
import java.awt.geom.GeneralPath; import java.awt.geom.GeneralPath;
import java.awt.geom.Line2D; import java.awt.geom.Line2D;
import java.awt.geom.Rectangle2D;
import java.awt.geom.RoundRectangle2D; import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.awt.image.BufferedImageOp; 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 Java graphics sets string coordinates by the baseline of the first character
so we need to shift down by the height of the textbox 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); _group.addShape(txt);
} }

View File

@ -17,6 +17,7 @@
package org.apache.poi.hslf.usermodel; package org.apache.poi.hslf.usermodel;
import java.awt.Rectangle;
import java.awt.geom.AffineTransform; import java.awt.geom.AffineTransform;
import java.awt.geom.GeneralPath; import java.awt.geom.GeneralPath;
import java.awt.geom.PathIterator; 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 * 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 <code>java.awt.geom.GeneralPath</code>. * and straight-line segments in the straight sections. This object closely corresponds to <code>java.awt.geom.GeneralPath</code>.
* </p> * </p>
* @author Yegor Kozlov
*/ */
public final class HSLFFreeformShape extends HSLFAutoShape implements FreeformShape<HSLFShape,HSLFTextParagraph> { public final class HSLFFreeformShape extends HSLFAutoShape implements FreeformShape<HSLFShape,HSLFTextParagraph> {
@ -90,7 +90,7 @@ public final class HSLFFreeformShape extends HSLFAutoShape implements FreeformSh
@Override @Override
public int setPath(GeneralPath path) { public int setPath(GeneralPath path) {
Rectangle2D bounds = path.getBounds2D(); Rectangle bounds = path.getBounds();
PathIterator it = path.getPathIterator(new AffineTransform()); PathIterator it = path.getPathIterator(new AffineTransform());
List<byte[]> segInfo = new ArrayList<byte[]>(); List<byte[]> segInfo = new ArrayList<byte[]>();
@ -241,7 +241,7 @@ public final class HSLFFreeformShape extends HSLFAutoShape implements FreeformSh
} }
} }
Rectangle2D anchor = getAnchor2D(); Rectangle2D anchor = getAnchor();
Rectangle2D bounds = path.getBounds2D(); Rectangle2D bounds = path.getBounds2D();
AffineTransform at = new AffineTransform(); AffineTransform at = new AffineTransform();
at.translate(anchor.getX(), anchor.getY()); at.translate(anchor.getX(), anchor.getY());

View File

@ -18,7 +18,6 @@
package org.apache.poi.hslf.usermodel; package org.apache.poi.hslf.usermodel;
import java.awt.Rectangle; import java.awt.Rectangle;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
@ -105,7 +104,7 @@ implements HSLFShapeContainer, GroupShape<HSLFShape,HSLFTextParagraph> {
} }
@Override @Override
public void setInteriorAnchor(Rectangle2D anchor){ public void setInteriorAnchor(Rectangle anchor){
EscherSpgrRecord spgr = getEscherChild(EscherSpgrRecord.RECORD_ID); EscherSpgrRecord spgr = getEscherChild(EscherSpgrRecord.RECORD_ID);
int x1 = Units.pointsToMaster(anchor.getX()); int x1 = Units.pointsToMaster(anchor.getX());
@ -121,13 +120,13 @@ implements HSLFShapeContainer, GroupShape<HSLFShape,HSLFTextParagraph> {
} }
@Override @Override
public Rectangle2D getInteriorAnchor(){ public Rectangle getInteriorAnchor(){
EscherSpgrRecord rec = getEscherChild(EscherSpgrRecord.RECORD_ID); EscherSpgrRecord rec = getEscherChild(EscherSpgrRecord.RECORD_ID);
double x1 = Units.masterToPoints(rec.getRectX1()); int x1 = (int)Units.masterToPoints(rec.getRectX1());
double y1 = Units.masterToPoints(rec.getRectY1()); int y1 = (int)Units.masterToPoints(rec.getRectY1());
double x2 = Units.masterToPoints(rec.getRectX2()); int x2 = (int)Units.masterToPoints(rec.getRectX2());
double y2 = Units.masterToPoints(rec.getRectY2()); int y2 = (int)Units.masterToPoints(rec.getRectY2());
return new Rectangle2D.Double(x1,y1,x2-x1,y2-y1); return new Rectangle(x1,y1,x2-x1,y2-y1);
} }
/** /**
@ -181,7 +180,7 @@ implements HSLFShapeContainer, GroupShape<HSLFShape,HSLFTextParagraph> {
* @param y the y coordinate of the top left corner of the shape in new location * @param y the y coordinate of the top left corner of the shape in new location
*/ */
public void moveTo(int x, int y){ public void moveTo(int x, int y){
java.awt.Rectangle anchor = getAnchor(); Rectangle anchor = getAnchor();
int dx = x - anchor.x; int dx = x - anchor.x;
int dy = y - anchor.y; int dy = y - anchor.y;
anchor.translate(dx, dy); anchor.translate(dx, dy);
@ -189,7 +188,7 @@ implements HSLFShapeContainer, GroupShape<HSLFShape,HSLFTextParagraph> {
for (HSLFShape shape : getShapes()) { for (HSLFShape shape : getShapes()) {
java.awt.Rectangle chanchor = shape.getAnchor(); Rectangle chanchor = shape.getAnchor();
chanchor.translate(dx, dy); chanchor.translate(dx, dy);
shape.setAnchor(chanchor); shape.setAnchor(chanchor);
} }
@ -201,7 +200,7 @@ implements HSLFShapeContainer, GroupShape<HSLFShape,HSLFTextParagraph> {
* *
* @return the anchor of this shape group * @return the anchor of this shape group
*/ */
public Rectangle2D getAnchor2D(){ public Rectangle getAnchor(){
EscherClientAnchorRecord clientAnchor = getEscherChild(EscherClientAnchorRecord.RECORD_ID); EscherClientAnchorRecord clientAnchor = getEscherChild(EscherClientAnchorRecord.RECORD_ID);
int x1,y1,x2,y2; int x1,y1,x2,y2;
if(clientAnchor == null){ if(clientAnchor == null){
@ -217,11 +216,11 @@ implements HSLFShapeContainer, GroupShape<HSLFShape,HSLFTextParagraph> {
x2 = clientAnchor.getDx1(); x2 = clientAnchor.getDx1();
y2 = clientAnchor.getRow1(); y2 = clientAnchor.getRow1();
} }
Rectangle2D anchor= new Rectangle2D.Double( Rectangle anchor= new Rectangle(
(x1 == -1 ? -1 : Units.masterToPoints(x1)), (int)(x1 == -1 ? -1 : Units.masterToPoints(x1)),
(y1 == -1 ? -1 : Units.masterToPoints(y1)), (int)(y1 == -1 ? -1 : Units.masterToPoints(y1)),
(x2 == -1 ? -1 : Units.masterToPoints(x2-x1)), (int)(x2 == -1 ? -1 : Units.masterToPoints(x2-x1)),
(y2 == -1 ? -1 : Units.masterToPoints(y2-y1)) (int)(y2 == -1 ? -1 : Units.masterToPoints(y2-y1))
); );
return anchor; return anchor;

View File

@ -17,6 +17,7 @@
package org.apache.poi.hslf.usermodel; package org.apache.poi.hslf.usermodel;
import java.awt.Dimension;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
import java.security.MessageDigest; import java.security.MessageDigest;
@ -219,4 +220,13 @@ public abstract class HSLFPictureData implements PictureData {
public final String getContentType() { public final String getContentType() {
return getType().contentType; return getType().contentType;
} }
@Override
public Dimension getImageDimensionInPixels() {
Dimension dim = getImageDimension();
return new Dimension(
Units.pointsToPixel(dim.getWidth()),
Units.pointsToPixel(dim.getHeight())
);
}
} }

View File

@ -17,9 +17,8 @@
package org.apache.poi.hslf.usermodel; package org.apache.poi.hslf.usermodel;
import java.awt.Dimension;
import java.awt.Insets; import java.awt.Insets;
import java.awt.geom.Rectangle2D; import java.awt.Rectangle;
import java.util.List; import java.util.List;
import org.apache.poi.ddf.AbstractEscherOptRecord; 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.EscherSimpleProperty;
import org.apache.poi.ddf.EscherSpRecord; import org.apache.poi.ddf.EscherSpRecord;
import org.apache.poi.hslf.record.Document; 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.PictureShape;
import org.apache.poi.sl.usermodel.ShapeContainer; import org.apache.poi.sl.usermodel.ShapeContainer;
import org.apache.poi.sl.usermodel.ShapeType; import org.apache.poi.sl.usermodel.ShapeType;
@ -113,21 +113,6 @@ public class HSLFPictureShape extends HSLFSimpleShape implements PictureShape<HS
return _escherContainer; return _escherContainer;
} }
/**
* 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 setDefaultSize(){
Dimension dim = getPictureData().getImageDimension();
Rectangle2D origRect = getAnchor2D();
double x = origRect.getX();
double y = origRect.getY();
double w = Units.pixelToPoints((int)dim.getWidth());
double h = Units.pixelToPoints((int)dim.getHeight());
setAnchor(new Rectangle2D.Double(x, y, w, h));
}
@Override @Override
public HSLFPictureData getPictureData(){ public HSLFPictureData getPictureData(){
HSLFSlideShow ppt = getSheet().getSlideShow(); HSLFSlideShow ppt = getSheet().getSlideShow();
@ -199,9 +184,9 @@ public class HSLFPictureShape extends HSLFSimpleShape implements PictureShape<HS
EscherBSERecord bse = getEscherBSERecord(); EscherBSERecord bse = getEscherBSERecord();
bse.setRef(bse.getRef() + 1); bse.setRef(bse.getRef() + 1);
java.awt.Rectangle anchor = getAnchor(); Rectangle anchor = getAnchor();
if (anchor.equals(new java.awt.Rectangle())){ if (anchor.isEmpty()){
setDefaultSize(); new DrawPictureShape(this).resize();
} }
} }

View File

@ -19,14 +19,29 @@ package org.apache.poi.hslf.usermodel;
import java.awt.Color; import java.awt.Color;
import java.awt.Graphics2D; import java.awt.Graphics2D;
import java.awt.geom.Rectangle2D; import java.awt.Rectangle;
import java.util.Iterator; import java.util.Iterator;
import org.apache.poi.ddf.*; import org.apache.poi.ddf.AbstractEscherOptRecord;
import org.apache.poi.ddf.EscherChildAnchorRecord;
import org.apache.poi.ddf.EscherClientAnchorRecord;
import org.apache.poi.ddf.EscherColorRef;
import org.apache.poi.ddf.EscherContainerRecord;
import org.apache.poi.ddf.EscherOptRecord;
import org.apache.poi.ddf.EscherProperties;
import org.apache.poi.ddf.EscherProperty;
import org.apache.poi.ddf.EscherRecord;
import org.apache.poi.ddf.EscherSimpleProperty;
import org.apache.poi.ddf.EscherSpRecord;
import org.apache.poi.hslf.record.ColorSchemeAtom; import org.apache.poi.hslf.record.ColorSchemeAtom;
import org.apache.poi.hslf.record.RecordTypes; import org.apache.poi.hslf.record.RecordTypes;
import org.apache.poi.sl.usermodel.*; import org.apache.poi.sl.usermodel.FillStyle;
import org.apache.poi.util.*; import org.apache.poi.sl.usermodel.Shape;
import org.apache.poi.sl.usermodel.ShapeContainer;
import org.apache.poi.sl.usermodel.ShapeType;
import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger;
import org.apache.poi.util.Units;
/** /**
* <p> * <p>
@ -126,18 +141,7 @@ public abstract class HSLFShape implements Shape<HSLFShape,HSLFTextParagraph> {
* *
* @return the anchor of this shape * @return the anchor of this shape
*/ */
public java.awt.Rectangle getAnchor(){ public 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(){
EscherSpRecord spRecord = getEscherChild(EscherSpRecord.RECORD_ID); EscherSpRecord spRecord = getEscherChild(EscherSpRecord.RECORD_ID);
int flags = spRecord.getFlags(); int flags = spRecord.getFlags();
int x1,y1,x2,y2; int x1,y1,x2,y2;
@ -160,11 +164,11 @@ public abstract class HSLFShape implements Shape<HSLFShape,HSLFTextParagraph> {
} }
// TODO: find out where this -1 value comes from at #57820 (link to ms docs?) // TODO: find out where this -1 value comes from at #57820 (link to ms docs?)
Rectangle2D anchor = new Rectangle2D.Double( Rectangle anchor = new Rectangle(
(x1 == -1 ? -1 : Units.masterToPoints(x1)), (int)(x1 == -1 ? -1 : Units.masterToPoints(x1)),
(y1 == -1 ? -1 : Units.masterToPoints(y1)), (int)(y1 == -1 ? -1 : Units.masterToPoints(y1)),
(x2 == -1 ? -1 : Units.masterToPoints(x2-x1)), (int)(x2 == -1 ? -1 : Units.masterToPoints(x2-x1)),
(y2 == -1 ? -1 : Units.masterToPoints(y2-y1)) (int)(y2 == -1 ? -1 : Units.masterToPoints(y2-y1))
); );
return anchor; return anchor;
@ -176,7 +180,7 @@ public abstract class HSLFShape implements Shape<HSLFShape,HSLFTextParagraph> {
* *
* @param anchor new anchor * @param anchor new anchor
*/ */
public void setAnchor(Rectangle2D anchor){ public void setAnchor(Rectangle anchor){
int x = Units.pointsToMaster(anchor.getX()); int x = Units.pointsToMaster(anchor.getX());
int y = Units.pointsToMaster(anchor.getY()); int y = Units.pointsToMaster(anchor.getY());
int w = Units.pointsToMaster(anchor.getWidth() + anchor.getX()); int w = Units.pointsToMaster(anchor.getWidth() + anchor.getX());
@ -206,7 +210,7 @@ public abstract class HSLFShape implements Shape<HSLFShape,HSLFTextParagraph> {
* @param y the y coordinate of the top left corner of the shape * @param y the y coordinate of the top left corner of the shape
*/ */
public void moveTo(float x, float y){ public void moveTo(float x, float y){
Rectangle2D anchor = getAnchor2D(); Rectangle anchor = getAnchor();
anchor.setRect(x, y, anchor.getWidth(), anchor.getHeight()); anchor.setRect(x, y, anchor.getWidth(), anchor.getHeight());
setAnchor(anchor); setAnchor(anchor);
} }

View File

@ -414,12 +414,12 @@ public abstract class HSLFSimpleShape extends HSLFShape implements SimpleShape<H
return clr == null ? Color.black : clr; return clr == null ? Color.black : clr;
} }
public Shadow getShadow() { public Shadow<HSLFShape,HSLFTextParagraph> getShadow() {
AbstractEscherOptRecord opt = getEscherOptRecord(); AbstractEscherOptRecord opt = getEscherOptRecord();
EscherProperty shadowType = opt.lookup(EscherProperties.SHADOWSTYLE__TYPE); EscherProperty shadowType = opt.lookup(EscherProperties.SHADOWSTYLE__TYPE);
if (shadowType == null) return null; if (shadowType == null) return null;
return new Shadow(){ return new Shadow<HSLFShape,HSLFTextParagraph>(){
public SimpleShape<HSLFShape,HSLFTextParagraph> getShadowParent() { public SimpleShape<HSLFShape,HSLFTextParagraph> getShadowParent() {
return HSLFSimpleShape.this; return HSLFSimpleShape.this;
} }

View File

@ -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.SlidePersistAtom;
import org.apache.poi.hslf.record.UserEditAtom; import org.apache.poi.hslf.record.UserEditAtom;
import org.apache.poi.poifs.filesystem.DirectoryNode; 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.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.sl.usermodel.MasterSheet; import org.apache.poi.sl.usermodel.MasterSheet;
import org.apache.poi.sl.usermodel.PictureData.PictureType; import org.apache.poi.sl.usermodel.PictureData.PictureType;
@ -159,8 +160,8 @@ public final class HSLFSlideShow implements SlideShow<HSLFShape,HSLFTextParagrap
/** /**
* Constructs a Powerpoint document from an POIFSFileSystem. * Constructs a Powerpoint document from an POIFSFileSystem.
*/ */
public HSLFSlideShow(POIFSFileSystem inputStream) throws IOException { public HSLFSlideShow(NPOIFSFileSystem npoifs) throws IOException {
this(new HSLFSlideShowImpl(inputStream)); this(new HSLFSlideShowImpl(npoifs));
} }
/** /**

View File

@ -0,0 +1,38 @@
/* ====================================================================
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 java.io.IOException;
import org.apache.poi.poifs.filesystem.NPOIFSFileSystem;
import org.apache.poi.sl.usermodel.SlideShow;
import org.apache.poi.sl.usermodel.SlideShowFactory;
import org.apache.poi.util.Internal;
@Internal
public class HSLFSlideShowFactory extends SlideShowFactory {
/**
* Creates a HSLFSlideShow from the given NPOIFSFileSystem
* <p>Note 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);
}
}

View File

@ -139,15 +139,15 @@ implements TextShape<HSLFShape,HSLFTextParagraph> {
storeText(); storeText();
EscherTextboxWrapper _txtbox = getEscherTextboxWrapper(); EscherTextboxWrapper thisTxtbox = getEscherTextboxWrapper();
if(_txtbox != null){ if(thisTxtbox != null){
_escherContainer.addChildRecord(_txtbox.getEscherRecord()); _escherContainer.addChildRecord(thisTxtbox.getEscherRecord());
PPDrawing ppdrawing = sh.getPPDrawing(); PPDrawing ppdrawing = sh.getPPDrawing();
ppdrawing.addTextboxWrapper(_txtbox); ppdrawing.addTextboxWrapper(thisTxtbox);
// Ensure the escher layer knows about the added records // Ensure the escher layer knows about the added records
try { try {
_txtbox.writeOut(null); thisTxtbox.writeOut(null);
} catch (IOException e){ } catch (IOException e){
throw new HSLFException(e); throw new HSLFException(e);
} }
@ -192,10 +192,10 @@ implements TextShape<HSLFShape,HSLFTextParagraph> {
* @return a <code>Rectangle2D</code> that is the bounds of this shape. * @return a <code>Rectangle2D</code> that is the bounds of this shape.
*/ */
public Rectangle2D resizeToFitText(){ public Rectangle2D resizeToFitText(){
Rectangle2D anchor = getAnchor(); Rectangle anchor = getAnchor();
if(anchor.getWidth() == 0.) { if(anchor.getWidth() == 0.) {
logger.log(POILogger.WARN, "Width of shape wasn't set. Defaulting to 200px"); 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); setAnchor(anchor);
} }
double height = getTextHeight(); double height = getTextHeight();

View File

@ -21,7 +21,7 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import java.awt.geom.Rectangle2D; import java.awt.Rectangle;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
@ -34,8 +34,6 @@ import org.junit.Test;
/** /**
* Test <code>MovieShape</code> object. * Test <code>MovieShape</code> object.
*
* @author Yegor Kozlov
*/ */
public final class TestMovieShape { public final class TestMovieShape {
@ -52,7 +50,7 @@ public final class TestMovieShape {
HSLFPictureData thumbnailData = ppt.addPicture(_slTests.readFile("tomcat.png"), PictureType.PNG); HSLFPictureData thumbnailData = ppt.addPicture(_slTests.readFile("tomcat.png"), PictureType.PNG);
MovieShape shape = new MovieShape(movieIdx, thumbnailData); 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); slide.addShape(shape);
assertEquals(path, shape.getPath()); assertEquals(path, shape.getPath());

View File

@ -20,18 +20,26 @@ package org.apache.poi.hslf.model;
import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import java.awt.geom.Rectangle2D; import java.awt.Rectangle;
import java.io.*; import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.InputStream;
import java.util.List; import java.util.List;
import org.apache.poi.POIDataSamples; 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.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hwpf.HWPFDocument; import org.apache.poi.hwpf.HWPFDocument;
import org.apache.poi.poifs.filesystem.POIFSFileSystem; 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.sl.usermodel.PictureData.PictureType;
import org.apache.poi.util.IOUtils;
import org.junit.Test; import org.junit.Test;
public final class TestOleEmbedding { public final class TestOleEmbedding {
@ -109,7 +117,7 @@ public final class TestOleEmbedding {
OLEShape oleShape1 = new OLEShape(pictData); OLEShape oleShape1 = new OLEShape(pictData);
oleShape1.setObjectID(oleObjectId1); oleShape1.setObjectID(oleObjectId1);
slide1.addShape(oleShape1); 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 // add second slide with different order in object creation
HSLFSlide slide2 = ppt.createSlide(); HSLFSlide slide2 = ppt.createSlide();
@ -123,7 +131,7 @@ public final class TestOleEmbedding {
oleShape2.setObjectID(oleObjectId2); oleShape2.setObjectID(oleObjectId2);
slide2.addShape(oleShape2); slide2.addShape(oleShape2);
oleShape2.setAnchor(new Rectangle2D.Double(100,100,100,100)); oleShape2.setAnchor(new Rectangle(100,100,100,100));
ByteArrayOutputStream bos = new ByteArrayOutputStream(); ByteArrayOutputStream bos = new ByteArrayOutputStream();
ppt.write(bos); ppt.write(bos);

View File

@ -27,7 +27,6 @@ import static org.junit.Assert.assertTrue;
import java.awt.Color; import java.awt.Color;
import java.awt.Dimension; import java.awt.Dimension;
import java.awt.Rectangle; import java.awt.Rectangle;
import java.awt.geom.Rectangle2D;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.IOException; import java.io.IOException;
@ -63,8 +62,6 @@ import org.junit.Test;
/** /**
* Test drawing shapes via Graphics2D * Test drawing shapes via Graphics2D
*
* @author Yegor Kozlov
*/ */
public final class TestShapes { public final class TestShapes {
private static POIDataSamples _slTests = POIDataSamples.getSlideShowInstance(); private static POIDataSamples _slTests = POIDataSamples.getSlideShowInstance();
@ -165,8 +162,8 @@ public final class TestShapes {
@SuppressWarnings("unused") @SuppressWarnings("unused")
@Test @Test
public void testParagraphs() throws Exception { public void testParagraphs() throws Exception {
HSLFSlideShow ppt = new HSLFSlideShow(); HSLFSlideShow ss = new HSLFSlideShow();
HSLFSlide slide = ppt.createSlide(); HSLFSlide slide = ss.createSlide();
HSLFTextBox shape = new HSLFTextBox(); HSLFTextBox shape = new HSLFTextBox();
HSLFTextRun p1r1 = shape.setText("para 1 run 1. "); HSLFTextRun p1r1 = shape.setText("para 1 run 1. ");
HSLFTextRun p1r2 = shape.appendText("para 1 run 2.", false); HSLFTextRun p1r2 = shape.appendText("para 1 run 2.", false);
@ -178,15 +175,15 @@ public final class TestShapes {
p2r2.setStrikethrough(true); p2r2.setStrikethrough(true);
// run 3 has same text properties as run 2 and will be merged when saving // run 3 has same text properties as run 2 and will be merged when saving
HSLFTextRun p2r3 = shape.appendText("para 2 run 3.", false); 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); slide.addShape(shape);
shape.resizeToFitText(); shape.resizeToFitText();
ByteArrayOutputStream bos = new ByteArrayOutputStream(); ByteArrayOutputStream bos = new ByteArrayOutputStream();
ppt.write(bos); ss.write(bos);
ppt = new HSLFSlideShow(new ByteArrayInputStream(bos.toByteArray())); ss = new HSLFSlideShow(new ByteArrayInputStream(bos.toByteArray()));
slide = ppt.getSlides().get(0); slide = ss.getSlides().get(0);
HSLFTextBox tb = (HSLFTextBox)slide.getShapes().get(0); HSLFTextBox tb = (HSLFTextBox)slide.getShapes().get(0);
List<HSLFTextParagraph> para = tb.getTextParagraphs(); List<HSLFTextParagraph> para = tb.getTextParagraphs();
HSLFTextRun tr = para.get(0).getTextRuns().get(0); HSLFTextRun tr = para.get(0).getTextRuns().get(0);
@ -289,8 +286,8 @@ public final class TestShapes {
} }
private void textBoxSet(String filename) throws Exception { private void textBoxSet(String filename) throws Exception {
HSLFSlideShow ppt = new HSLFSlideShow(_slTests.openResourceAsStream(filename)); HSLFSlideShow ss = new HSLFSlideShow(_slTests.openResourceAsStream(filename));
for (HSLFSlide sld : ppt.getSlides()) { for (HSLFSlide sld : ss.getSlides()) {
ArrayList<String> lst1 = new ArrayList<String>(); ArrayList<String> lst1 = new ArrayList<String>();
for (List<HSLFTextParagraph> txt : sld.getTextParagraphs()) { for (List<HSLFTextParagraph> txt : sld.getTextParagraphs()) {
for (HSLFTextParagraph p : txt) { for (HSLFTextParagraph p : txt) {
@ -321,17 +318,17 @@ public final class TestShapes {
*/ */
@Test @Test
public void shapeGroup() throws Exception { public void shapeGroup() throws Exception {
HSLFSlideShow ppt = new HSLFSlideShow(); HSLFSlideShow ss = new HSLFSlideShow();
HSLFSlide slide = ppt.createSlide(); HSLFSlide slide = ss.createSlide();
Dimension pgsize = ppt.getPageSize(); Dimension pgsize = ss.getPageSize();
HSLFGroupShape group = new HSLFGroupShape(); HSLFGroupShape group = new HSLFGroupShape();
group.setAnchor(new Rectangle(0, 0, (int)pgsize.getWidth(), (int)pgsize.getHeight())); group.setAnchor(new Rectangle(0, 0, (int)pgsize.getWidth(), (int)pgsize.getHeight()));
slide.addShape(group); 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); HSLFPictureShape pict = new HSLFPictureShape(data, group);
pict.setAnchor(new Rectangle(0, 0, 200, 200)); pict.setAnchor(new Rectangle(0, 0, 200, 200));
group.addShape(pict); group.addShape(pict);
@ -342,14 +339,14 @@ public final class TestShapes {
//serialize and read again. //serialize and read again.
ByteArrayOutputStream out = new ByteArrayOutputStream(); ByteArrayOutputStream out = new ByteArrayOutputStream();
ppt.write(out); ss.write(out);
out.close(); out.close();
ByteArrayInputStream is = new ByteArrayInputStream(out.toByteArray()); ByteArrayInputStream is = new ByteArrayInputStream(out.toByteArray());
ppt = new HSLFSlideShow(is); ss = new HSLFSlideShow(is);
is.close(); is.close();
slide = ppt.getSlides().get(0); slide = ss.getSlides().get(0);
List<HSLFShape> shape = slide.getShapes(); List<HSLFShape> shape = slide.getShapes();
assertEquals(1, shape.size()); assertEquals(1, shape.size());
@ -374,8 +371,8 @@ public final class TestShapes {
@Test @Test
public void removeShapes() throws IOException { public void removeShapes() throws IOException {
String file = "with_textbox.ppt"; String file = "with_textbox.ppt";
HSLFSlideShow ppt = new HSLFSlideShow(_slTests.openResourceAsStream(file)); HSLFSlideShow ss = new HSLFSlideShow(_slTests.openResourceAsStream(file));
HSLFSlide sl = ppt.getSlides().get(0); HSLFSlide sl = ss.getSlides().get(0);
List<HSLFShape> sh = sl.getShapes(); List<HSLFShape> sh = sl.getShapes();
assertEquals("expected four shaped in " + file, 4, sh.size()); assertEquals("expected four shaped in " + file, 4, sh.size());
//remove all //remove all
@ -388,11 +385,11 @@ public final class TestShapes {
//serialize and read again. The file should be readable and contain no shapes //serialize and read again. The file should be readable and contain no shapes
ByteArrayOutputStream out = new ByteArrayOutputStream(); ByteArrayOutputStream out = new ByteArrayOutputStream();
ppt.write(out); ss.write(out);
out.close(); out.close();
ppt = new HSLFSlideShow(new ByteArrayInputStream(out.toByteArray())); ss = new HSLFSlideShow(new ByteArrayInputStream(out.toByteArray()));
sl = ppt.getSlides().get(0); sl = ss.getSlides().get(0);
assertEquals("expected 0 shaped in " + file, 0, sl.getShapes().size()); assertEquals("expected 0 shaped in " + file, 0, sl.getShapes().size());
} }
@ -413,12 +410,12 @@ public final class TestShapes {
@Test @Test
public void shapeId() { public void shapeId() {
HSLFSlideShow ppt = new HSLFSlideShow(); HSLFSlideShow ss = new HSLFSlideShow();
HSLFSlide slide = ppt.createSlide(); HSLFSlide slide = ss.createSlide();
HSLFShape shape = null; HSLFShape shape = null;
//EscherDgg is a document-level record which keeps track of the drawing groups //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(); EscherDgRecord dg = slide.getSheetContainer().getPPDrawing().getEscherDgRecord();
int dggShapesUsed = dgg.getNumShapesSaved(); //total number of shapes in the ppt int dggShapesUsed = dgg.getNumShapesSaved(); //total number of shapes in the ppt
@ -463,8 +460,8 @@ public final class TestShapes {
@Test @Test
public void lineColor() throws IOException { public void lineColor() throws IOException {
HSLFSlideShow ppt = new HSLFSlideShow(_slTests.openResourceAsStream("51731.ppt")); HSLFSlideShow ss = new HSLFSlideShow(_slTests.openResourceAsStream("51731.ppt"));
List<HSLFShape> shape = ppt.getSlides().get(0).getShapes(); List<HSLFShape> shape = ss.getSlides().get(0).getShapes();
assertEquals(4, shape.size()); assertEquals(4, shape.size());

View File

@ -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");
}
}

View File

@ -35,6 +35,7 @@ import org.apache.poi.hslf.blip.PICT;
import org.apache.poi.hslf.blip.PNG; import org.apache.poi.hslf.blip.PNG;
import org.apache.poi.hslf.blip.WMF; import org.apache.poi.hslf.blip.WMF;
import org.apache.poi.sl.usermodel.PictureData.PictureType; import org.apache.poi.sl.usermodel.PictureData.PictureType;
import org.apache.poi.util.Units;
import org.junit.Ignore; import org.junit.Ignore;
import org.junit.Test; import org.junit.Test;
@ -46,8 +47,6 @@ import org.junit.Test;
public final class TestPictures { public final class TestPictures {
private static POIDataSamples slTests = POIDataSamples.getSlideShowInstance(); private static POIDataSamples slTests = POIDataSamples.getSlideShowInstance();
//protected File cwd;
/** /**
* Test read/write Macintosh PICT * Test read/write Macintosh PICT
*/ */
@ -64,9 +63,9 @@ public final class TestPictures {
assertEquals(expWidth, nDim.getWidth(), 0); assertEquals(expWidth, nDim.getWidth(), 0);
assertEquals(expHeight, nDim.getHeight(), 0); assertEquals(expHeight, nDim.getHeight(), 0);
Dimension dim = data.getImageDimension(); Dimension dim = data.getImageDimensionInPixels();
assertEquals(expWidth, dim.getWidth(), 0); assertEquals(Units.pointsToPixel(expWidth), dim.getWidth(), 0);
assertEquals(expHeight, dim.getHeight(), 0); assertEquals(Units.pointsToPixel(expHeight), dim.getHeight(), 0);
HSLFPictureShape pict = new HSLFPictureShape(data); HSLFPictureShape pict = new HSLFPictureShape(data);
assertEquals(data.getIndex(), pict.getPictureIndex()); assertEquals(data.getIndex(), pict.getPictureIndex());
@ -127,9 +126,9 @@ public final class TestPictures {
assertEquals(expWidth, nDim.getWidth(), 0); assertEquals(expWidth, nDim.getWidth(), 0);
assertEquals(expHeight, nDim.getHeight(), 0); assertEquals(expHeight, nDim.getHeight(), 0);
Dimension dim = data.getImageDimension(); Dimension dim = data.getImageDimensionInPixels();
assertEquals(expWidth, dim.getWidth(), 0); assertEquals(Units.pointsToPixel(expWidth), dim.getWidth(), 0);
assertEquals(expHeight, dim.getHeight(), 0); assertEquals(Units.pointsToPixel(expHeight), dim.getHeight(), 0);
HSLFPictureShape pict = new HSLFPictureShape(data); HSLFPictureShape pict = new HSLFPictureShape(data);
assertEquals(data.getIndex(), pict.getPictureIndex()); assertEquals(data.getIndex(), pict.getPictureIndex());
@ -189,9 +188,9 @@ public final class TestPictures {
assertEquals(expWidth, nDim.getWidth(), 0); assertEquals(expWidth, nDim.getWidth(), 0);
assertEquals(expHeight, nDim.getHeight(), 0); assertEquals(expHeight, nDim.getHeight(), 0);
Dimension dim = data.getImageDimension(); Dimension dim = data.getImageDimensionInPixels();
assertEquals(expWidth, dim.getWidth(), 0); assertEquals(Units.pointsToPixel(expWidth), dim.getWidth(), 0);
assertEquals(expHeight, dim.getHeight(), 0); assertEquals(Units.pointsToPixel(expHeight), dim.getHeight(), 0);
HSLFPictureShape pict = new HSLFPictureShape(data); HSLFPictureShape pict = new HSLFPictureShape(data);
assertEquals(data.getIndex(), pict.getPictureIndex()); assertEquals(data.getIndex(), pict.getPictureIndex());

View File

@ -22,19 +22,14 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import java.awt.Rectangle;
import java.awt.geom.GeneralPath; import java.awt.geom.GeneralPath;
import java.awt.geom.Rectangle2D;
import java.net.URL; import java.net.URL;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.Map; import java.util.Map;
import org.junit.Test; import org.junit.Test;
/**
* Date: 10/24/11
*
* @author Yegor Kozlov
*/
public class TestPresetGeometries { public class TestPresetGeometries {
@Test @Test
public void testRead(){ public void testRead(){
@ -43,8 +38,8 @@ public class TestPresetGeometries {
for(String name : shapes.keySet()) { for(String name : shapes.keySet()) {
CustomGeometry geom = shapes.get(name); CustomGeometry geom = shapes.get(name);
Context ctx = new Context(geom, new Rectangle2D.Double(0, 0, 100, 100), new IAdjustableShape() { Context ctx = new Context(geom, new Rectangle(0, 0, 100, 100), new IAdjustableShape() {
public Guide getAdjustValue(String name) { public Guide getAdjustValue(String presetName) {
return null; return null;
} }
}); });

View File

@ -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);
}
}