import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assumptions.assumeFalse;
+import java.io.Closeable;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
+import org.mockito.internal.util.io.IOUtil;
/**
* Test class for testing PPTX2PNG utility which renders .ppt and .pptx slideshows
*/
@SuppressWarnings("ConstantConditions")
class TestPPTX2PNG {
+ private static Closeable archive;
private static boolean xslfOnly;
private static final POIDataSamples samples = POIDataSamples.getSlideShowInstance();
@AfterAll
public static void resetStdin() {
System.setIn(defStdin);
+ IOUtil.closeQuietly(archive);
}
public static Stream<Arguments> data() throws IOException {
+ // Junit closes all closable arguments after the usage
+ // therefore we need to wrap the archive in non-closable arrays
+
if (basedir != null && basedir.getName().endsWith(".zip")) {
ZipFile zipFile = new ZipFile(basedir);
- return zipFile.stream().map(f -> Arguments.of(f.getName(), f, zipFile));
+ archive = zipFile;
+ return zipFile.stream().map(f -> Arguments.of(f.getName(), f, new ZipFile[]{zipFile}));
} else if (basedir != null && basedir.getName().endsWith(".7z")) {
SevenZFile sevenZFile = new SevenZFile(basedir);
- return ((ArrayList<SevenZArchiveEntry>)sevenZFile.getEntries()).stream().filter(f -> !f.isDirectory()).map(f -> Arguments.of(f.getName(), f, sevenZFile));
+ archive = sevenZFile;
+ return ((ArrayList<SevenZArchiveEntry>)sevenZFile.getEntries()).stream().filter(f -> !f.isDirectory()).map(f -> Arguments.of(f.getName(), f, new SevenZFile[]{sevenZFile}));
} else {
return Stream.of(files.split(", ?")).
map(basedir == null ? samples::getFile : f -> new File(basedir, f)).
"-format", format, // png,gif,jpg,svg,pdf or null for test
"-slide", "-1", // -1 for all
"-outdir", tmpDir.getCanonicalPath(),
- // "-dump", new File("build/tmp/", pptFile+".json").getCanonicalPath(),
+ // "-dump", new File("build/tmp/", fileName+".json").getCanonicalPath(),
"-dump", "null",
"-quiet",
"-ignoreParse",
if (fileObj instanceof ZipEntry) {
ZipEntry ze = (ZipEntry)fileObj;
- ZipFile zf = (ZipFile)fileContainer;
+ ZipFile zf = ((ZipFile[])fileContainer)[0];
System.setIn(zf.getInputStream(ze));
args.add("-outpat");
args.add(basename+"-${slideno}-"+ext+".${format}");
args.add("stdin");
} else if (fileObj instanceof SevenZArchiveEntry) {
SevenZArchiveEntry ze = (SevenZArchiveEntry)fileObj;
- SevenZFile zf = (SevenZFile)fileContainer;
+ SevenZFile zf = ((SevenZFile[])fileContainer)[0];
System.setIn(zf.getInputStream(ze));
args.add("-outpat");
args.add(basename+"-${slideno}-"+ext+".${format}");
package org.apache.poi.hemf.record.emf;
+import static org.apache.logging.log4j.util.Unbox.box;
+
import java.awt.geom.Rectangle2D;
import java.io.IOException;
import java.nio.charset.Charset;
import org.apache.poi.common.usermodel.GenericRecord;
import org.apache.poi.hemf.draw.HemfGraphics;
import org.apache.poi.hemf.draw.HemfGraphics.EmfRenderState;
+import org.apache.poi.hemf.record.emf.HemfRecord.RenderBounds;
import org.apache.poi.hemf.record.emfplus.HemfPlusRecord;
import org.apache.poi.hemf.record.emfplus.HemfPlusRecordIterator;
import org.apache.poi.hwmf.usermodel.HwmfCharsetAware;
import org.apache.poi.util.LocaleUtil;
import org.apache.poi.util.RecordFormatException;
-import static org.apache.logging.log4j.util.Unbox.box;
-
/**
* Contains arbitrary data
*/
*/
default void draw(HemfGraphics ctx) {}
- default void calcBounds(Rectangle2D bounds, Rectangle2D viewport, EmfRenderState[] renderState) { }
+ default void calcBounds(RenderBounds holder) { }
@Override
}
@Override
- public void calcBounds(Rectangle2D window, Rectangle2D viewport, EmfRenderState[] renderState) {
- data.calcBounds(window, viewport, renderState);
+ public void calcBounds(RenderBounds holder) {
+ data.calcBounds(holder);
}
@Override
}
@Override
- public void calcBounds(Rectangle2D window, Rectangle2D viewport, EmfRenderState[] renderState) {
- renderState[0] = EmfRenderState.EMFPLUS_ONLY;
+ public void calcBounds(RenderBounds holder) {
+ holder.setState(EmfRenderState.EMFPLUS_ONLY);
for (HemfPlusRecord r : records) {
- r.calcBounds(window, viewport, renderState);
- if (!window.isEmpty() && !viewport.isEmpty()) {
+ r.calcBounds(holder);
+ if (!holder.getWindow().isEmpty() && !holder.getViewport().isEmpty()) {
break;
}
}
public HemfRecordType getGenericRecordType() {
return getEmfRecordType();
}
+
+ @Override
+ public void calcBounds(RenderBounds holder) {
+ Rectangle2D b = holder.getBounds();
+ if (b.isEmpty()) {
+ b.setRect(bounds);
+ } else {
+ b.add(bounds);
+ }
+ }
}
/**
public HemfRecordType getGenericRecordType() {
return getEmfRecordType();
}
+
+ @Override
+ public void calcBounds(RenderBounds holder) {
+ Rectangle2D b = holder.getBounds();
+ if (b.isEmpty()) {
+ b.setRect(bounds);
+ } else {
+ b.add(bounds);
+ }
+ }
}
/**
public HemfRecordType getGenericRecordType() {
return getEmfRecordType();
}
+
+ @Override
+ public void calcBounds(RenderBounds holder) {
+ Rectangle2D b = holder.getBounds();
+ if (b.isEmpty()) {
+ b.setRect(bounds);
+ } else {
+ b.add(bounds);
+ }
+ }
}
/**
public HemfRecordType getGenericRecordType() {
return getEmfRecordType();
}
+
+ @Override
+ public void calcBounds(RenderBounds holder) {
+ Rectangle2D b = holder.getBounds();
+ if (b.isEmpty()) {
+ b.setRect(bounds);
+ } else {
+ b.add(bounds);
+ }
+ }
}
/**
public HemfRecordType getGenericRecordType() {
return getEmfRecordType();
}
+
+ @Override
+ public void calcBounds(RenderBounds holder) {
+ Rectangle2D b = holder.getBounds();
+ if (!b.isEmpty()) {
+ b.add(point);
+ }
+ }
}
/**
public HemfRecordType getGenericRecordType() {
return getEmfRecordType();
}
+
+ @Override
+ public void calcBounds(RenderBounds holder) {
+ Rectangle2D b = holder.getBounds();
+ if (b.isEmpty()) {
+ b.setRect(bounds);
+ } else {
+ b.add(bounds);
+ }
+ }
}
/** The EMR_POLYDRAW record specifies a set of line segments and Bezier curves. */
public HemfRecordType getGenericRecordType() {
return getEmfRecordType();
}
+
+ @Override
+ public void calcBounds(RenderBounds holder) {
+ Rectangle2D b = holder.getBounds();
+ if (b.isEmpty()) {
+ b.setRect(bounds);
+ } else {
+ b.add(bounds);
+ }
+ }
}
public static class EmfPolyDraw16 extends EmfPolyDraw {
public Map<String, Supplier<?>> getGenericProperties() {
return GenericRecordUtil.getGenericProperties("bounds", this::getBounds);
}
+
+ @Override
+ public void calcBounds(RenderBounds holder) {
+ Rectangle2D b = holder.getBounds();
+ if (b.isEmpty()) {
+ b.setRect(bounds);
+ } else {
+ b.add(bounds);
+ }
+ }
}
}
}
- default void calcBounds(Rectangle2D window, Rectangle2D viewport, HemfGraphics.EmfRenderState[] renderState) {
+ interface RenderBounds {
+ HemfGraphics.EmfRenderState getState();
+ void setState(HemfGraphics.EmfRenderState state);
+
+ Rectangle2D getWindow();
+ Rectangle2D getViewport();
+ Rectangle2D getBounds();
+ }
+
+ default void calcBounds(RenderBounds holder) {
}
/**
}
@Override
- public void calcBounds(Rectangle2D window, Rectangle2D viewport, HemfGraphics.EmfRenderState[] renderState) {
+ public void calcBounds(RenderBounds holder) {
+ Rectangle2D window = holder.getWindow();
double x = window.getX();
double y = window.getY();
window.setRect(x,y,size.getWidth(),size.getHeight());
}
@Override
- public void calcBounds(Rectangle2D window, Rectangle2D viewport, HemfGraphics.EmfRenderState[] renderState) {
+ public void calcBounds(RenderBounds holder) {
+ Rectangle2D window = holder.getWindow();
double w = window.getWidth();
double h = window.getHeight();
window.setRect(origin.getX(),origin.getY(),w,h);
}
@Override
- public void calcBounds(Rectangle2D window, Rectangle2D viewport, HemfGraphics.EmfRenderState[] renderState) {
+ public void calcBounds(RenderBounds holder) {
+ Rectangle2D viewport = holder.getViewport();
double x = viewport.getX();
double y = viewport.getY();
viewport.setRect(x,y,extents.getWidth(),extents.getHeight());
}
@Override
- public void calcBounds(Rectangle2D window, Rectangle2D viewport, HemfGraphics.EmfRenderState[] renderState) {
+ public void calcBounds(RenderBounds holder) {
+ Rectangle2D viewport = holder.getViewport();
double w = viewport.getWidth();
double h = viewport.getHeight();
viewport.setRect(origin.getX(), origin.getY(), w, h);
public HemfRecordType getGenericRecordType() {
return getEmfRecordType();
}
+
+ @Override
+ public void calcBounds(RenderBounds holder) {
+ Rectangle2D b = holder.getBounds();
+ if (b.isEmpty()) {
+ b.setRect(bounds);
+ } else {
+ b.add(bounds);
+ }
+ }
}
/**
}
@Override
- public void calcBounds(Rectangle2D window, Rectangle2D viewport, HemfGraphics.EmfRenderState[] renderState) {
+ public void calcBounds(RenderBounds holder) {
+ Rectangle2D viewport = holder.getViewport();
double x = viewport.getX();
double y = viewport.getY();
double w = viewport.getWidth();
}
@Override
- public void calcBounds(Rectangle2D window, Rectangle2D viewport, HemfGraphics.EmfRenderState[] renderState) {
+ public void calcBounds(RenderBounds holder) {
+ Rectangle2D window = holder.getWindow();
double x = window.getX();
double y = window.getY();
double w = window.getWidth();
import static org.apache.poi.util.GenericRecordUtil.getEnumBitsAsString;
-import java.awt.geom.Rectangle2D;
import java.io.IOException;
import java.util.Map;
import java.util.function.Supplier;
import org.apache.poi.common.usermodel.GenericRecord;
import org.apache.poi.hemf.draw.HemfGraphics;
import org.apache.poi.hemf.draw.HemfGraphics.EmfRenderState;
+import org.apache.poi.hemf.record.emf.HemfRecord.RenderBounds;
import org.apache.poi.util.BitField;
import org.apache.poi.util.BitFieldFactory;
import org.apache.poi.util.GenericRecordJsonWriter;
}
@Override
- public void calcBounds(Rectangle2D window, Rectangle2D viewport, EmfRenderState[] renderState) {
- renderState[0] = EmfRenderState.EMF_DCONTEXT;
+ public void calcBounds(RenderBounds holder) {
+ holder.setState(EmfRenderState.EMF_DCONTEXT);
}
@Override
import org.apache.poi.hemf.draw.HemfDrawProperties;
import org.apache.poi.hemf.draw.HemfGraphics;
import org.apache.poi.hemf.record.emf.HemfFill;
+import org.apache.poi.hemf.record.emf.HemfRecord.RenderBounds;
import org.apache.poi.hwmf.record.HwmfRegionMode;
import org.apache.poi.util.BitField;
import org.apache.poi.util.BitFieldFactory;
}
@Override
- public void calcBounds(Rectangle2D window, Rectangle2D viewport, HemfGraphics.EmfRenderState[] renderState) {
- renderState[0] = HemfGraphics.EmfRenderState.EMF_DCONTEXT;
+ public void calcBounds(RenderBounds holder) {
+ holder.setState(HemfGraphics.EmfRenderState.EMF_DCONTEXT);
}
}
package org.apache.poi.hemf.record.emfplus;
-import java.awt.geom.Rectangle2D;
import java.io.IOException;
import org.apache.poi.common.usermodel.GenericRecord;
import org.apache.poi.hemf.draw.HemfGraphics;
+import org.apache.poi.hemf.record.emf.HemfRecord.RenderBounds;
import org.apache.poi.util.Internal;
import org.apache.poi.util.LittleEndianInputStream;
default void draw(HemfGraphics ctx) {
}
- default void calcBounds(Rectangle2D window, Rectangle2D viewport, HemfGraphics.EmfRenderState[] renderState) {
+ default void calcBounds(RenderBounds holder) {
}
@Override
import static java.lang.Math.abs;
+import static java.util.Comparator.comparingDouble;
import static org.apache.poi.hemf.draw.HemfGraphics.EmfRenderState.EMFPLUS_ONLY;
import static org.apache.poi.hemf.draw.HemfGraphics.EmfRenderState.EMF_ONLY;
import java.util.Spliterator;
import java.util.function.Consumer;
import java.util.function.Supplier;
+import java.util.stream.Stream;
import org.apache.poi.common.usermodel.GenericRecord;
import org.apache.poi.hemf.draw.HemfGraphics;
import org.apache.poi.hemf.record.emf.HemfComment;
import org.apache.poi.hemf.record.emf.HemfHeader;
import org.apache.poi.hemf.record.emf.HemfRecord;
+import org.apache.poi.hemf.record.emf.HemfRecord.RenderBounds;
import org.apache.poi.hemf.record.emf.HemfRecordIterator;
import org.apache.poi.hwmf.usermodel.HwmfCharsetAware;
import org.apache.poi.hwmf.usermodel.HwmfEmbedded;
boolean isInvalid = ReluctantRectangle2D.isEmpty(dim);
if (isInvalid) {
Rectangle2D lastDim = new ReluctantRectangle2D();
- getInnerBounds(lastDim, new ReluctantRectangle2D());
+ getInnerBounds(lastDim, new Rectangle2D.Double(), new Rectangle2D.Double());
if (!lastDim.isEmpty()) {
return lastDim;
}
return dim;
}
- public void getInnerBounds(Rectangle2D window, Rectangle2D viewport) {
- HemfGraphics.EmfRenderState[] renderState = { HemfGraphics.EmfRenderState.INITIAL };
+ public void getInnerBounds(Rectangle2D window, Rectangle2D viewport, Rectangle2D bounds) {
+ RenderBounds holder = new RenderBounds() {
+ private HemfGraphics.EmfRenderState state = HemfGraphics.EmfRenderState.INITIAL;
+
+ @Override
+ public HemfGraphics.EmfRenderState getState() {
+ return state;
+ }
+
+ @Override
+ public void setState(HemfGraphics.EmfRenderState state) {
+ this.state = state;
+ }
+
+ @Override
+ public Rectangle2D getWindow() {
+ return window;
+ }
+
+ @Override
+ public Rectangle2D getViewport() {
+ return viewport;
+ }
+
+ @Override
+ public Rectangle2D getBounds() {
+ return bounds;
+ }
+ };
+
for (HemfRecord r : getRecords()) {
if (
- (renderState[0] == EMF_ONLY && r instanceof HemfComment.EmfComment) ||
- (renderState[0] == EMFPLUS_ONLY && !(r instanceof HemfComment.EmfComment))
+ (holder.getState() == EMF_ONLY && r instanceof HemfComment.EmfComment) ||
+ (holder.getState() == EMFPLUS_ONLY && !(r instanceof HemfComment.EmfComment))
) {
continue;
}
try {
- r.calcBounds(window, viewport, renderState);
+ r.calcBounds(holder);
} catch (RuntimeException ignored) {
}
- if (!window.isEmpty() && !viewport.isEmpty()) {
- break;
- }
+// if (!window.isEmpty() && !viewport.isEmpty()) {
+// break;
+// }
}
}
Rectangle2D emfBounds = getHeader().getBoundsRectangle();
Rectangle2D winBounds = new ReluctantRectangle2D();
Rectangle2D viewBounds = new ReluctantRectangle2D();
- getInnerBounds(winBounds, viewBounds);
+ Rectangle2D recBounds = new Rectangle2D.Double();
+ getInnerBounds(winBounds, viewBounds, recBounds);
Boolean forceHeader = (Boolean)ctx.getRenderingHint(Drawable.EMF_FORCE_HEADER_BOUNDS);
if (forceHeader == null) {
forceHeader = false;
}
- // this is a compromise ... sometimes winBounds are totally off :(
- // but mostly they fit better than the header bounds
- Rectangle2D b =
- !viewBounds.isEmpty() && !forceHeader
- ? viewBounds
- : !winBounds.isEmpty() && !forceHeader
- ? winBounds
- : emfBounds;
+
+ Rectangle2D b;
+ if (forceHeader) {
+ b = emfBounds;
+ } else if (recBounds.isEmpty()) {
+ // this is a compromise ... sometimes winBounds are totally off :(
+ // but mostly they fit better than the header bounds
+ b = !viewBounds.isEmpty()
+ ? viewBounds
+ : !winBounds.isEmpty()
+ ? winBounds
+ : emfBounds;
+ } else {
+ double recHyp = dia(recBounds);
+ b = Stream.of(emfBounds, winBounds, viewBounds).
+ min(comparingDouble(r -> abs(dia(r) - recHyp))).get();
+ }
ctx.translate(graphicsBounds.getCenterX(), graphicsBounds.getCenterY());
ctx.scale(
}
}
+ private static double dia(Rectangle2D bounds) {
+ return Math.sqrt(bounds.getWidth()*bounds.getWidth() + bounds.getHeight()*bounds.getWidth());
+ }
+
public Iterable<HwmfEmbedded> getEmbeddings() {
return () -> new HemfEmbeddedIterator(HemfPicture.this);
}