You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@poi.apache.org by ki...@apache.org on 2019/09/11 21:24:08 UTC
svn commit: r1866808 [2/7] - in /poi: site/src/documentation/content/xdocs/
trunk/src/java/org/apache/poi/common/usermodel/
trunk/src/java/org/apache/poi/common/usermodel/fonts/
trunk/src/java/org/apache/poi/ddf/ trunk/src/java/org/apache/poi/hssf/user...
Modified: poi/trunk/src/java/org/apache/poi/poifs/crypt/EncryptionVerifier.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/poifs/crypt/EncryptionVerifier.java?rev=1866808&r1=1866807&r2=1866808&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/poifs/crypt/EncryptionVerifier.java (original)
+++ poi/trunk/src/java/org/apache/poi/poifs/crypt/EncryptionVerifier.java Wed Sep 11 21:24:06 2019
@@ -16,10 +16,17 @@
==================================================================== */
package org.apache.poi.poifs.crypt;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.function.Supplier;
+
+import org.apache.poi.common.usermodel.GenericRecord;
+
/**
* Used when checking if a key is valid for a document
*/
-public abstract class EncryptionVerifier implements Cloneable {
+public abstract class EncryptionVerifier implements Cloneable, GenericRecord {
private byte[] salt;
private byte[] encryptedVerifier;
private byte[] encryptedVerifierHash;
@@ -105,4 +112,18 @@ public abstract class EncryptionVerifier
other.encryptedKey = (encryptedKey == null) ? null : encryptedKey.clone();
return other;
}
+
+ @Override
+ public Map<String, Supplier<?>> getGenericProperties() {
+ final Map<String,Supplier<?>> m = new LinkedHashMap<>();
+ m.put("salt", this::getSalt);
+ m.put("encryptedVerifier", this::getEncryptedVerifier);
+ m.put("encryptedVerifierHash", this::getEncryptedVerifierHash);
+ m.put("encryptedKey", this::getEncryptedKey);
+ m.put("spinCount", this::getSpinCount);
+ m.put("cipherAlgorithm", this::getCipherAlgorithm);
+ m.put("chainingMode", this::getChainingMode);
+ m.put("hashAlgorithm", this::getHashAlgorithm);
+ return Collections.unmodifiableMap(m);
+ }
}
Modified: poi/trunk/src/java/org/apache/poi/poifs/crypt/Encryptor.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/poifs/crypt/Encryptor.java?rev=1866808&r1=1866807&r2=1866808&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/poifs/crypt/Encryptor.java (original)
+++ poi/trunk/src/java/org/apache/poi/poifs/crypt/Encryptor.java Wed Sep 11 21:24:06 2019
@@ -19,15 +19,19 @@ package org.apache.poi.poifs.crypt;
import java.io.IOException;
import java.io.OutputStream;
import java.security.GeneralSecurityException;
+import java.util.Map;
+import java.util.function.Supplier;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import org.apache.poi.EncryptedDocumentException;
+import org.apache.poi.common.usermodel.GenericRecord;
import org.apache.poi.poifs.filesystem.DirectoryNode;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
+import org.apache.poi.util.GenericRecordUtil;
-public abstract class Encryptor implements Cloneable {
+public abstract class Encryptor implements Cloneable, GenericRecord {
protected static final String DEFAULT_POIFS_ENTRY = Decryptor.DEFAULT_POIFS_ENTRY;
private EncryptionInfo encryptionInfo;
private SecretKey secretKey;
@@ -93,4 +97,11 @@ public abstract class Encryptor implemen
// encryptionInfo is set from outside
return other;
}
+
+ @Override
+ public Map<String, Supplier<?>> getGenericProperties() {
+ return GenericRecordUtil.getGenericProperties(
+ "secretKey", secretKey::getEncoded
+ );
+ }
}
Modified: poi/trunk/src/java/org/apache/poi/sl/draw/DrawPictureShape.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/sl/draw/DrawPictureShape.java?rev=1866808&r1=1866807&r2=1866808&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/sl/draw/DrawPictureShape.java (original)
+++ poi/trunk/src/java/org/apache/poi/sl/draw/DrawPictureShape.java Wed Sep 11 21:24:06 2019
@@ -76,9 +76,9 @@ public class DrawPictureShape extends Dr
* @param graphics the graphics context
* @return the image renderer
*/
- @SuppressWarnings({"WeakerAccess", "unchecked"})
+ @SuppressWarnings({"unchecked"})
public static ImageRenderer getImageRenderer(Graphics2D graphics, String contentType) {
- final ImageRenderer renderer = (ImageRenderer)graphics.getRenderingHint(Drawable.IMAGE_RENDERER);
+ final ImageRenderer renderer = (graphics != null) ? (ImageRenderer)graphics.getRenderingHint(Drawable.IMAGE_RENDERER) : null;
if (renderer != null && renderer.canRender(contentType)) {
return renderer;
}
Modified: poi/trunk/src/java/org/apache/poi/sl/draw/DrawSimpleShape.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/sl/draw/DrawSimpleShape.java?rev=1866808&r1=1866807&r2=1866808&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/sl/draw/DrawSimpleShape.java (original)
+++ poi/trunk/src/java/org/apache/poi/sl/draw/DrawSimpleShape.java Wed Sep 11 21:24:06 2019
@@ -23,8 +23,8 @@ import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Paint;
+import java.awt.Stroke;
import java.awt.geom.AffineTransform;
-import java.awt.geom.Area;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Path2D;
import java.awt.geom.Rectangle2D;
@@ -62,6 +62,10 @@ public class DrawSimpleShape extends Dra
return;
}
+ Paint oldPaint = graphics.getPaint();
+ Stroke oldStroke = graphics.getStroke();
+ Color oldColor = graphics.getColor();
+
Paint fill = getFillPaint(graphics);
Paint line = getLinePaint(graphics);
BasicStroke stroke = getStroke(); // the stroke applies both to the shadow and the shape
@@ -115,8 +119,12 @@ public class DrawSimpleShape extends Dra
}
}
- // draw line decorations
+ // draw line decorations
drawDecoration(graphics, line, stroke);
+
+ graphics.setColor(oldColor);
+ graphics.setPaint(oldPaint);
+ graphics.setStroke(oldStroke);
}
private void fillArea(Graphics2D graphics, PaintModifier pm, Path2D area) {
Modified: poi/trunk/src/java/org/apache/poi/sl/draw/ImageRenderer.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/sl/draw/ImageRenderer.java?rev=1866808&r1=1866807&r2=1866808&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/sl/draw/ImageRenderer.java (original)
+++ poi/trunk/src/java/org/apache/poi/sl/draw/ImageRenderer.java Wed Sep 11 21:24:06 2019
@@ -26,6 +26,8 @@ import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;
+import org.apache.poi.common.usermodel.GenericRecord;
+
/**
* Classes can implement this interfaces to support other formats, for
* example, use Apache Batik to render WMF, PICT can be rendered using Apple QuickTime API for Java:
@@ -134,4 +136,7 @@ public interface ImageRenderer {
* @return true if the picture data was successfully rendered
*/
boolean drawImage(Graphics2D graphics, Rectangle2D anchor, Insets clip);
+
+ default GenericRecord getGenericRecord() { return null; }
+
}
\ No newline at end of file
Modified: poi/trunk/src/java/org/apache/poi/sl/usermodel/TextShape.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/sl/usermodel/TextShape.java?rev=1866808&r1=1866807&r2=1866808&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/sl/usermodel/TextShape.java (original)
+++ poi/trunk/src/java/org/apache/poi/sl/usermodel/TextShape.java Wed Sep 11 21:24:06 2019
@@ -105,21 +105,38 @@ public interface TextShape<
*/
enum TextPlaceholder {
/** Title placeholder shape text */
- TITLE,
+ TITLE(0),
/** Body placeholder shape text */
- BODY,
+ BODY(1),
/** Center title placeholder shape text */
- CENTER_TITLE,
+ CENTER_TITLE(6),
/** Center body placeholder shape text */
- CENTER_BODY,
+ CENTER_BODY(5),
/** Half-sized body placeholder shape text */
- HALF_BODY,
+ HALF_BODY(7),
/** Quarter-sized body placeholder shape text */
- QUARTER_BODY,
+ QUARTER_BODY(8),
/** Notes placeholder shape text */
- NOTES,
+ NOTES(2),
/** Any other text */
- OTHER
+ OTHER(4);
+
+ public final int nativeId;
+
+ TextPlaceholder(int nativeId) {
+ this.nativeId = nativeId;
+ }
+
+ public static TextPlaceholder fromNativeId(int nativeId) {
+ for (TextPlaceholder ld : values()) {
+ if (ld.nativeId == nativeId) return ld;
+ }
+ return null;
+ }
+
+ public static boolean isTitle(int nativeId) {
+ return (nativeId == TITLE.nativeId || nativeId == CENTER_TITLE.nativeId);
+ }
}
/**
Added: poi/trunk/src/java/org/apache/poi/util/GenericRecordJsonWriter.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/util/GenericRecordJsonWriter.java?rev=1866808&view=auto
==============================================================================
--- poi/trunk/src/java/org/apache/poi/util/GenericRecordJsonWriter.java (added)
+++ poi/trunk/src/java/org/apache/poi/util/GenericRecordJsonWriter.java Wed Sep 11 21:24:06 2019
@@ -0,0 +1,455 @@
+/*
+ * ====================================================================
+ * 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.util;
+
+import java.awt.Color;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Dimension2D;
+import java.awt.geom.Path2D;
+import java.awt.geom.PathIterator;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+import java.io.Closeable;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.Flushable;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.io.Writer;
+import java.lang.reflect.Array;
+import java.nio.charset.StandardCharsets;
+import java.util.AbstractMap;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.function.BiConsumer;
+import java.util.function.Supplier;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.xml.bind.DatatypeConverter;
+
+import org.apache.poi.common.usermodel.GenericRecord;
+import org.apache.poi.util.GenericRecordUtil.AnnotatedFlag;
+
+@Beta
+public class GenericRecordJsonWriter implements Closeable {
+ private static final String TABS;
+ private static final String ZEROS = "0000000000000000";
+ private static final Pattern ESC_CHARS = Pattern.compile("[\"\\p{Cntrl}\\\\]");
+
+ private static final List<Map.Entry<Class,BiConsumer<GenericRecordJsonWriter,Object>>> handler = new ArrayList<>();
+
+ static {
+ char[] t = new char[255];
+ Arrays.fill(t, '\t');
+ TABS = new String(t);
+ handler(String.class, GenericRecordJsonWriter::printObject);
+ handler(Number.class, GenericRecordJsonWriter::printNumber);
+ handler(Boolean.class, GenericRecordJsonWriter::printBoolean);
+ handler(List.class, GenericRecordJsonWriter::printList);
+ handler(GenericRecord.class, GenericRecordJsonWriter::printGenericRecord);
+ handler(AnnotatedFlag.class, GenericRecordJsonWriter::printAnnotatedFlag);
+ handler(byte[].class, GenericRecordJsonWriter::printBytes);
+ handler(Point2D.class, GenericRecordJsonWriter::printPoint);
+ handler(Dimension2D.class, GenericRecordJsonWriter::printDimension);
+ handler(Rectangle2D.class, GenericRecordJsonWriter::printRectangle);
+ handler(Path2D.class, GenericRecordJsonWriter::printPath);
+ handler(AffineTransform.class, GenericRecordJsonWriter::printAffineTransform);
+ handler(Color.class, GenericRecordJsonWriter::printColor);
+ handler(Array.class, GenericRecordJsonWriter::printArray);
+ handler(Object.class, GenericRecordJsonWriter::printObject);
+ }
+
+ private static void handler(Class c, BiConsumer<GenericRecordJsonWriter,Object> printer) {
+ handler.add(new AbstractMap.SimpleEntry<>(c,printer));
+ }
+
+ private final PrintWriter fw;
+ private int indent = 0;
+ private boolean withComments = true;
+ private int childIndex = 0;
+
+ public GenericRecordJsonWriter(File fileName) throws IOException {
+ OutputStream os = ("null".equals(fileName.getName())) ? new NullOutputStream() : new FileOutputStream(fileName);
+ fw = new PrintWriter(new OutputStreamWriter(os, StandardCharsets.UTF_8));
+ }
+
+ public GenericRecordJsonWriter(Appendable buffer) {
+ fw = new PrintWriter(new Writer(){
+ @Override
+ public void write(char[] cbuf, int off, int len) throws IOException {
+ buffer.append(String.valueOf(cbuf), off, len);
+ }
+
+ @Override
+ public void flush() throws IOException {
+ if (buffer instanceof Flushable) {
+ ((Flushable)buffer).flush();
+ }
+ }
+
+ @Override
+ public void close() throws IOException {
+ flush();
+ if (buffer instanceof Closeable) {
+ ((Closeable)buffer).close();
+ }
+ }
+ });
+ }
+
+ public static String marshal(GenericRecord record) {
+ return marshal(record, true);
+ }
+
+ public static String marshal(GenericRecord record, boolean withComments) {
+ final StringBuilder sb = new StringBuilder();
+ try (GenericRecordJsonWriter w = new GenericRecordJsonWriter(sb)) {
+ w.setWithComments(withComments);
+ w.write(record);
+ return sb.toString();
+ } catch (IOException e) {
+ return "{}";
+ }
+ }
+
+ public void setWithComments(boolean withComments) {
+ this.withComments = withComments;
+ }
+
+ @Override
+ public void close() throws IOException {
+ fw.close();
+ }
+
+ private String tabs() {
+ return TABS.substring(0, Math.min(indent, TABS.length()));
+ }
+
+ public void write(GenericRecord record) {
+ final String tabs = tabs();
+ Enum type = record.getGenericRecordType();
+ String recordName = (type != null) ? type.name() : record.getClass().getSimpleName();
+ fw.append(tabs);
+ fw.append("{");
+ if (withComments) {
+ fw.append(" /* ");
+ fw.append(recordName);
+ if (childIndex > 0) {
+ fw.append(" - index: ");
+ fw.print(childIndex);
+ }
+ fw.append(" */");
+ }
+ fw.println();
+
+ Map<String, Supplier<?>> prop = record.getGenericProperties();
+ if (prop != null) {
+ final int oldChildIndex = childIndex;
+ childIndex = 0;
+ prop.forEach(this::writeProp);
+ childIndex = oldChildIndex;
+ }
+
+ fw.println();
+ List<? extends GenericRecord> list = record.getGenericChildren();
+ if (list != null && !list.isEmpty()) {
+ indent++;
+ fw.append(tabs());
+ if (prop != null && !prop.isEmpty()) {
+ fw.append(", ");
+ }
+ fw.append("children: [");
+ final int oldChildIndex = childIndex;
+ childIndex = 0;
+ list.forEach(l -> { writeValue(l); childIndex++; });
+ childIndex = oldChildIndex;
+ fw.println();
+ fw.append(tabs());
+ fw.append("]");
+ fw.println();
+ indent--;
+ }
+
+ fw.append(tabs);
+ fw.append("}");
+ }
+
+ public void writeError(String errorMsg) {
+ fw.append("{ error: ");
+ printObject(errorMsg);
+ fw.append(" }");
+ }
+
+ private void writeProp(String k, Supplier<?> v) {
+ final boolean isNext = (childIndex++>0);
+ if (isNext) {
+ fw.println();
+ }
+ fw.write(tabs());
+ fw.write('\t');
+ fw.write(isNext ? ", " : " ");
+ fw.write(k);
+ fw.write(": ");
+ final int oldChildIndex = childIndex;
+ childIndex = 0;
+ writeValue(v.get());
+ childIndex = oldChildIndex;
+ }
+
+ private void writeValue(Object o) {
+ if (childIndex > 0) {
+ fw.println(',');
+ }
+ if (o == null) {
+ fw.write("null");
+ } else {
+ handler.stream().
+ filter(h -> matchInstanceOrArray(h.getKey(), o)).
+ findFirst().
+ ifPresent(h -> h.getValue().accept(this, o));
+ }
+ }
+
+ private static boolean matchInstanceOrArray(Class key, Object instance) {
+ return key.isInstance(instance) || (Array.class.equals(key) && instance.getClass().isArray());
+ }
+
+ private void printNumber(Object o) {
+ Number n = (Number)o;
+ fw.print(n.toString());
+
+ final int size;
+ if (n instanceof Byte) {
+ size = 2;
+ } else if (n instanceof Short) {
+ size = 4;
+ } else if (n instanceof Integer) {
+ size = 8;
+ } else if (n instanceof Long) {
+ size = 16;
+ } else {
+ size = -1;
+ }
+
+ long l = n.longValue();
+ if (withComments && size > 0 && (l < 0 || l > 9)) {
+ fw.write(" /* 0x");
+ fw.write(trimHex(l, size));
+ fw.write(" */");
+ }
+ }
+
+ private void printBoolean(Object o) {
+ fw.write(((Boolean)o).toString());
+ }
+
+ private void printList(Object o) {
+ fw.println('[');
+ final int[] c = new int[1];
+ //noinspection unchecked
+ int oldChildIndex = childIndex;
+ childIndex = 0;
+ ((List)o).forEach(e -> { writeValue(e); childIndex++; });
+ childIndex = oldChildIndex;
+ fw.write(']');
+ }
+
+ private void printGenericRecord(Object o) {
+ fw.println();
+ this.indent++;
+ write((GenericRecord) o);
+ this.indent--;
+ }
+
+ private void printAnnotatedFlag(Object o) {
+ AnnotatedFlag af = (AnnotatedFlag) o;
+ fw.write("0x");
+ fw.write(Long.toHexString(af.getValue().get().longValue()));
+ if (withComments) {
+ fw.write(" /* ");
+ fw.write(af.getDescription());
+ fw.write(" */ ");
+ }
+ }
+
+ private void printBytes(Object o) {
+ fw.write('"');
+ fw.write(DatatypeConverter.printBase64Binary((byte[]) o));
+ fw.write('"');
+ }
+
+ private void printPoint(Object o) {
+ Point2D p = (Point2D)o;
+ fw.write("{ x: "+p.getX()+", y: "+p.getY()+" }");
+ }
+
+ private void printDimension(Object o) {
+ Dimension2D p = (Dimension2D)o;
+ fw.write("{ width: "+p.getWidth()+", height: "+p.getHeight()+" }");
+ }
+
+ private void printRectangle(Object o) {
+ Rectangle2D p = (Rectangle2D)o;
+ fw.write("{ x: "+p.getX()+", y: "+p.getY()+", width: "+p.getWidth()+", height: "+p.getHeight()+" }");
+ }
+
+ private void printPath(Object o) {
+ final PathIterator iter = ((Path2D)o).getPathIterator(null);
+ final double[] pnts = new double[6];
+ fw.print("[");
+
+ indent += 2;
+ String t = tabs();
+ indent -= 2;
+
+ boolean isNext = false;
+ while (!iter.isDone()) {
+ fw.println(isNext ? ", " : "");
+ fw.print(t);
+ isNext = true;
+ final int segType = iter.currentSegment(pnts);
+ fw.append("{ type: ");
+ switch (segType) {
+ case PathIterator.SEG_MOVETO:
+ fw.write("'move', x: "+pnts[0]+", y: "+pnts[1]);
+ break;
+ case PathIterator.SEG_LINETO:
+ fw.write("'lineto', x: "+pnts[0]+", y: "+pnts[1]);
+ break;
+ case PathIterator.SEG_QUADTO:
+ fw.write("'quad', x1: "+pnts[0]+", y1: "+pnts[1]+", x2: "+pnts[2]+", y2: "+pnts[3]);
+ break;
+ case PathIterator.SEG_CUBICTO:
+ fw.write("'cubic', x1: "+pnts[0]+", y1: "+pnts[1]+", x2: "+pnts[2]+", y2: "+pnts[3]+", x3: "+pnts[4]+", y3: "+pnts[5]);
+ break;
+ case PathIterator.SEG_CLOSE:
+ fw.write("'close'");
+ break;
+ }
+ fw.append(" }");
+ iter.next();
+ }
+
+ fw.write("]");
+ }
+
+ private void printObject(Object o) {
+ fw.write('"');
+
+ final Matcher m = ESC_CHARS.matcher(o.toString());
+ final StringBuffer sb = new StringBuffer();
+ while (m.find()) {
+ String repl;
+ String match = m.group();
+ switch (match) {
+ case "\n":
+ repl = "\\\\n";
+ break;
+ case "\r":
+ repl = "\\\\r";
+ break;
+ case "\t":
+ repl = "\\\\t";
+ break;
+ case "\b":
+ repl = "\\\\b";
+ break;
+ case "\f":
+ repl = "\\\\f";
+ break;
+ case "\\":
+ repl = "\\\\\\\\";
+ break;
+ case "\"":
+ repl = "\\\\\"";
+ break;
+ default:
+ repl = "\\\\u" + trimHex(match.charAt(0), 4);
+ break;
+ }
+ m.appendReplacement(sb, repl);
+ }
+ m.appendTail(sb);
+ fw.write(sb.toString());
+
+ fw.write('"');
+ }
+
+ private void printAffineTransform(Object o) {
+ AffineTransform xForm = (AffineTransform)o;
+ fw.write(
+ "{ scaleX: "+xForm.getScaleX()+
+ ", shearX: "+xForm.getShearX()+
+ ", transX: "+xForm.getTranslateX()+
+ ", scaleY: "+xForm.getScaleY()+
+ ", shearY: "+xForm.getShearY()+
+ ", transY: "+xForm.getTranslateY()+" }");
+ }
+
+ private void printColor(Object o) {
+ final int rgb = ((Color)o).getRGB();
+ fw.print(rgb);
+
+ if (withComments) {
+ fw.write(" /* 0x");
+ fw.write(trimHex(rgb, 8));
+ fw.write(" */");
+ }
+ }
+
+ private void printArray(Object o) {
+ fw.println('[');
+ int length = Array.getLength(o);
+ final int oldChildIndex = childIndex;
+ for (childIndex=0; childIndex<length; childIndex++) {
+ writeValue(Array.get(o, childIndex));
+ }
+ childIndex = oldChildIndex;
+ fw.write(']');
+ }
+
+ private String trimHex(final long l, final int size) {
+ final String b = Long.toHexString(l);
+ int len = b.length();
+ return ZEROS.substring(0, Math.max(0,size-len)) + b.substring(Math.max(0,len-size), len);
+ }
+
+ private static class NullOutputStream extends OutputStream {
+ private NullOutputStream() {
+ }
+
+ @Override
+ public void write(byte[] b, int off, int len) {
+ }
+
+ @Override
+ public void write(int b) {
+ }
+
+ @Override
+ public void write(byte[] b) {
+ }
+ }
+}
Propchange: poi/trunk/src/java/org/apache/poi/util/GenericRecordJsonWriter.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: poi/trunk/src/java/org/apache/poi/util/GenericRecordUtil.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/util/GenericRecordUtil.java?rev=1866808&view=auto
==============================================================================
--- poi/trunk/src/java/org/apache/poi/util/GenericRecordUtil.java (added)
+++ poi/trunk/src/java/org/apache/poi/util/GenericRecordUtil.java Wed Sep 11 21:24:06 2019
@@ -0,0 +1,142 @@
+/*
+ * ====================================================================
+ * 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.util;
+
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.function.Supplier;
+import java.util.stream.Collectors;
+
+@Internal
+public final class GenericRecordUtil {
+ private GenericRecordUtil() {}
+
+ public static Map<String, Supplier<?>>
+ getGenericProperties(String val1, Supplier<?> sup1) {
+ return Collections.unmodifiableMap(Collections.singletonMap(val1, sup1));
+ }
+
+ public static Map<String, Supplier<?>> getGenericProperties(
+ String val1, Supplier<?> sup1,
+ String val2, Supplier<?> sup2
+ ) {
+ return getGenericProperties(val1, sup1, val2, sup2, null, null, null, null, null, null, null, null);
+ }
+
+ public static Map<String, Supplier<?>> getGenericProperties(
+ String val1, Supplier<?> sup1,
+ String val2, Supplier<?> sup2,
+ String val3, Supplier<?> sup3
+ ) {
+ return getGenericProperties(val1, sup1, val2, sup2, val3, sup3, null, null, null, null, null, null);
+ }
+
+ public static Map<String, Supplier<?>> getGenericProperties(
+ String val1, Supplier<?> sup1,
+ String val2, Supplier<?> sup2,
+ String val3, Supplier<?> sup3,
+ String val4, Supplier<?> sup4
+ ) {
+ return getGenericProperties(val1, sup1, val2, sup2, val3, sup3, val4, sup4, null, null, null, null);
+
+ }
+
+ public static Map<String, Supplier<?>> getGenericProperties(
+ String val1, Supplier<?> sup1,
+ String val2, Supplier<?> sup2,
+ String val3, Supplier<?> sup3,
+ String val4, Supplier<?> sup4,
+ String val5, Supplier<?> sup5
+ ) {
+ return getGenericProperties(val1, sup1, val2, sup2, val3, sup3, val4, sup4, val5, sup5, null, null);
+ }
+
+ public static Map<String, Supplier<?>> getGenericProperties(
+ String val1, Supplier<?> sup1,
+ String val2, Supplier<?> sup2,
+ String val3, Supplier<?> sup3,
+ String val4, Supplier<?> sup4,
+ String val5, Supplier<?> sup5,
+ String val6, Supplier<?> sup6
+ ) {
+ final Map<String,Supplier<?>> m = new LinkedHashMap<>();
+
+ final String[] vals = { val1, val2, val3, val4, val5, val6 };
+ final Supplier<?>[] sups = { sup1, sup2, sup3, sup4, sup5, sup6 };
+
+ for (int i=0; i<vals.length && vals[i] != null; i++) {
+ assert(sups[i] != null);
+ if ("base".equals(vals[i])) {
+ Object baseMap = sups[i].get();
+ assert(baseMap instanceof Map);
+ //noinspection unchecked
+ m.putAll((Map<String,Supplier<?>>)baseMap);
+ } else {
+ m.put(vals[i], sups[i]);
+ }
+ }
+
+ return Collections.unmodifiableMap(m);
+ }
+
+ public static <T extends Enum> Supplier<T> safeEnum(T[] values, Supplier<Number> ordinal) {
+ return safeEnum(values, ordinal, null);
+ }
+
+ public static <T extends Enum> Supplier<T> safeEnum(T[] values, Supplier<Number> ordinal, T defaultVal) {
+ int ord = ordinal.get().intValue();
+ return () -> (0 <= ord && ord < values.length) ? values[ord] : defaultVal;
+ }
+
+ public static Supplier<AnnotatedFlag> getBitsAsString(Supplier<Number> flags, final int[] masks, final String[] names) {
+ return () -> new AnnotatedFlag(flags, masks, names);
+ }
+
+ public static class AnnotatedFlag {
+ private final Supplier<Number> value;
+ private final Map<Integer,String> masks = new LinkedHashMap<>();
+
+ AnnotatedFlag(Supplier<Number> value, int[] masks, String[] names) {
+ assert(masks.length == names.length);
+
+ this.value = value;
+ for (int i=0; i<masks.length; i++) {
+ this.masks.put(masks[i], names[i]);
+ }
+ }
+
+ public Supplier<Number> getValue() {
+ return value;
+ }
+
+ public String getDescription() {
+ final int val = value.get().intValue();
+ return masks.entrySet().stream().
+ filter(e -> match(val, e.getKey())).
+ map(Map.Entry::getValue).
+ collect(Collectors.joining(" | "));
+ }
+
+ private static boolean match(final int val, int mask) {
+ return (val & mask) == mask;
+ }
+ }
+}
Propchange: poi/trunk/src/java/org/apache/poi/util/GenericRecordUtil.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: poi/trunk/src/ooxml/java/org/apache/poi/poifs/crypt/agile/AgileEncryptionHeader.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/ooxml/java/org/apache/poi/poifs/crypt/agile/AgileEncryptionHeader.java?rev=1866808&r1=1866807&r2=1866808&view=diff
==============================================================================
--- poi/trunk/src/ooxml/java/org/apache/poi/poifs/crypt/agile/AgileEncryptionHeader.java (original)
+++ poi/trunk/src/ooxml/java/org/apache/poi/poifs/crypt/agile/AgileEncryptionHeader.java Wed Sep 11 21:24:06 2019
@@ -16,16 +16,19 @@
==================================================================== */
package org.apache.poi.poifs.crypt.agile;
-import org.apache.poi.EncryptedDocumentException;
-import org.apache.poi.poifs.crypt.ChainingMode;
-import org.apache.poi.poifs.crypt.CipherAlgorithm;
-import org.apache.poi.poifs.crypt.EncryptionHeader;
-import org.apache.poi.poifs.crypt.HashAlgorithm;
+import java.util.Map;
+import java.util.function.Supplier;
import com.microsoft.schemas.office.x2006.encryption.CTDataIntegrity;
import com.microsoft.schemas.office.x2006.encryption.CTKeyData;
import com.microsoft.schemas.office.x2006.encryption.EncryptionDocument;
import com.microsoft.schemas.office.x2006.encryption.STCipherChaining;
+import org.apache.poi.EncryptedDocumentException;
+import org.apache.poi.poifs.crypt.ChainingMode;
+import org.apache.poi.poifs.crypt.CipherAlgorithm;
+import org.apache.poi.poifs.crypt.EncryptionHeader;
+import org.apache.poi.poifs.crypt.HashAlgorithm;
+import org.apache.poi.util.GenericRecordUtil;
public class AgileEncryptionHeader extends EncryptionHeader implements Cloneable {
private byte[] encryptedHmacKey;
@@ -132,4 +135,12 @@ public class AgileEncryptionHeader exten
return other;
}
+ @Override
+ public Map<String, Supplier<?>> getGenericProperties() {
+ return GenericRecordUtil.getGenericProperties(
+ "base", super::getGenericProperties,
+ "encryptedHmacKey", this::getEncryptedHmacKey,
+ "encryptedHmacValue", this::getEncryptedHmacValue
+ );
+ }
}
Modified: poi/trunk/src/ooxml/java/org/apache/poi/xslf/util/PPTX2PNG.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/ooxml/java/org/apache/poi/xslf/util/PPTX2PNG.java?rev=1866808&r1=1866807&r2=1866808&view=diff
==============================================================================
--- poi/trunk/src/ooxml/java/org/apache/poi/xslf/util/PPTX2PNG.java (original)
+++ poi/trunk/src/ooxml/java/org/apache/poi/xslf/util/PPTX2PNG.java Wed Sep 11 21:24:06 2019
@@ -19,24 +19,45 @@
package org.apache.poi.xslf.util;
-import java.awt.Dimension;
+import static java.util.Spliterator.NONNULL;
+import static java.util.Spliterator.ORDERED;
+
+import java.awt.AlphaComposite;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
+import java.awt.geom.Dimension2D;
+import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
+import java.io.Closeable;
import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
import java.lang.ref.WeakReference;
-import java.util.List;
+import java.util.Collections;
import java.util.Locale;
import java.util.Set;
+import java.util.Spliterator;
+import java.util.Spliterators.AbstractSpliterator;
import java.util.TreeSet;
+import java.util.function.Consumer;
+import java.util.regex.Matcher;
import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
import javax.imageio.ImageIO;
+import org.apache.poi.common.usermodel.GenericRecord;
+import org.apache.poi.sl.draw.DrawPictureShape;
import org.apache.poi.sl.draw.Drawable;
+import org.apache.poi.sl.draw.ImageRenderer;
+import org.apache.poi.sl.usermodel.PictureData;
import org.apache.poi.sl.usermodel.Slide;
import org.apache.poi.sl.usermodel.SlideShow;
import org.apache.poi.sl.usermodel.SlideShowFactory;
+import org.apache.poi.util.GenericRecordJsonWriter;
/**
* An utility to convert slides of a .pptx slide show to a PNG image
@@ -57,12 +78,14 @@ public class PPTX2PNG {
(error == null ? "" : ("Error: "+error+"\n")) +
"Options:\n" +
" -scale <float> scale factor\n" +
+ " -fixSide <side> specify side (long,short,width,height) to fix - use <scale> as amount of pixels\n" +
" -slide <integer> 1-based index of a slide to render\n" +
" -format <type> png,gif,jpg (,null for testing)\n" +
" -outdir <dir> output directory, defaults to origin of the ppt/pptx file\n" +
" -outfile <file> output filename, defaults to '"+OUTPUT_PAT_REGEX+"'\n" +
" -outpat <pattern> output filename pattern, defaults to '"+OUTPUT_PAT_REGEX+"'\n" +
" patterns: basename, slideno, format, ext\n" +
+ " -dump <file> dump the annotated records to a file\n" +
" -quiet do not write to console (for normal processing)";
System.out.println(msg);
@@ -82,7 +105,10 @@ public class PPTX2PNG {
File outdir = null;
String outfile = null;
boolean quiet = false;
- String outpattern = OUTPUT_PAT_REGEX;
+ String outPattern = OUTPUT_PAT_REGEX;
+ File dumpfile = null;
+ String fixSide = "scale";
+
for (int i = 0; i < args.length; i++) {
String opt = (i+1 < args.length) ? args[i+1] : null;
@@ -108,12 +134,20 @@ public class PPTX2PNG {
i++;
break;
case "-outpat":
- outpattern = opt;
+ outPattern = opt;
i++;
break;
case "-quiet":
quiet = true;
break;
+ case "-dump":
+ dumpfile = new File(opt);
+ i++;
+ break;
+ case "-fixside":
+ fixSide = opt.toLowerCase(Locale.ROOT);
+ i++;
+ break;
default:
file = new File(args[i]);
break;
@@ -144,28 +178,64 @@ public class PPTX2PNG {
return;
}
+ if (!"long,short,width,height,scale".contains(fixSide)) {
+ usage("<fixside> must be one of long / short / width / height");
+ return;
+ }
+
if (!quiet) {
System.out.println("Processing " + file);
}
- try (SlideShow<?, ?> ss = SlideShowFactory.create(file, null, true)) {
- List<? extends Slide<?, ?>> slides = ss.getSlides();
- Set<Integer> slidenum = slideIndexes(slides.size(), slidenumStr);
+ try (MFProxy proxy = initProxy(file)) {
+ final Set<Integer> slidenum = proxy.slideIndexes(slidenumStr);
if (slidenum.isEmpty()) {
- usage("slidenum must be either -1 (for all) or within range: [1.." + slides.size() + "] for " + file);
+ usage("slidenum must be either -1 (for all) or within range: [1.." + proxy.getSlideCount() + "] for " + file);
return;
}
- Dimension pgsize = ss.getPageSize();
- int width = (int) (pgsize.width * scale);
- int height = (int) (pgsize.height * scale);
-
- for (Integer slideNo : slidenum) {
- Slide<?, ?> slide = slides.get(slideNo);
- String title = slide.getTitle();
+ final Dimension2D pgsize = proxy.getSize();
+ final double lenSide;
+ switch (fixSide) {
+ default:
+ case "scale":
+ lenSide = 1;
+ break;
+ case "long":
+ lenSide = Math.max(pgsize.getWidth(), pgsize.getHeight());
+ break;
+ case "short":
+ lenSide = Math.min(pgsize.getWidth(), pgsize.getHeight());
+ break;
+ case "width":
+ lenSide = pgsize.getWidth();
+ break;
+ case "height":
+ lenSide = pgsize.getHeight();
+ break;
+ }
+
+ final int width = (int) Math.rint(pgsize.getWidth() * scale / lenSide);
+ final int height = (int) Math.rint(pgsize.getHeight() * scale / lenSide);
+
+
+ for (int slideNo : slidenum) {
+ proxy.setSlideNo(slideNo);
if (!quiet) {
- System.out.println("Rendering slide " + (slideNo+1) + (title == null ? "" : ": " + title.trim()));
+ String title = proxy.getTitle();
+ System.out.println("Rendering slide " + (slideNo + 1) + (title == null ? "" : ": " + title.trim()));
+ }
+
+ GenericRecord gr = proxy.getRoot();
+ if (dumpfile != null) {
+ try (GenericRecordJsonWriter fw = new GenericRecordJsonWriter(dumpfile)) {
+ if (gr == null) {
+ fw.writeError(file.getName()+" doesn't support GenericRecord interface and can't be dumped to a file.");
+ } else {
+ fw.write(gr);
+ }
+ }
}
BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
@@ -174,19 +244,25 @@ public class PPTX2PNG {
// default rendering options
graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
graphics.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
+ graphics.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_SPEED);
graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
graphics.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
graphics.setRenderingHint(Drawable.BUFFERED_IMAGE, new WeakReference<>(img));
- graphics.scale(scale, scale);
+ graphics.scale(scale / lenSide, scale / lenSide);
+
+ graphics.setComposite(AlphaComposite.Clear);
+ graphics.fillRect(0, 0, (int)width, (int)height);
+ graphics.setComposite(AlphaComposite.SrcOver);
// draw stuff
- slide.draw(graphics);
+ proxy.draw(graphics);
// save the result
if (!"null".equals(format)) {
- String inname = String.format(Locale.ROOT, "%04d|%s|%s", slideNo+1, format, file.getName());
- String outname = (outfile != null) ? outfile : INPUT_PATTERN.matcher(inname).replaceAll(outpattern);
+ String inname = String.format(Locale.ROOT, "%04d|%s|%s", slideNo, format, file.getName());
+ String outpat = (proxy.getSlideCount() > 1 ? outPattern : outPattern.replaceAll("-?\\$\\{slideno\\}", ""));
+ String outname = (outfile != null) ? outfile : INPUT_PATTERN.matcher(inname).replaceAll(outpat);
ImageIO.write(img, format, new File(outdir, outname));
}
@@ -200,42 +276,181 @@ public class PPTX2PNG {
}
}
- private static Set<Integer> slideIndexes(final int slideCount, String range) {
- Set<Integer> slideIdx = new TreeSet<>();
- if ("-1".equals(range)) {
- for (int i=0; i<slideCount; i++) {
- slideIdx.add(i);
- }
- } else {
- for (String subrange : range.split(",")) {
- String[] idx = subrange.split("-");
- switch (idx.length) {
- default:
- case 0: break;
- case 1: {
- int subidx = Integer.parseInt(idx[0]);
- if (subrange.contains("-")) {
- int startIdx = subrange.startsWith("-") ? 0 : subidx;
- int endIdx = subrange.endsWith("-") ? slideCount : Math.min(subidx,slideCount);
- for (int i=Math.max(startIdx,1); i<endIdx; i++) {
- slideIdx.add(i-1);
- }
- } else {
- slideIdx.add(Math.max(subidx,1)-1);
- }
- break;
- }
- case 2: {
- int startIdx = Math.min(Integer.parseInt(idx[0]), slideCount);
- int endIdx = Math.min(Integer.parseInt(idx[1]), slideCount);
- for (int i=Math.max(startIdx,1); i<endIdx; i++) {
- slideIdx.add(i-1);
+ private static MFProxy initProxy(File file) throws IOException {
+ MFProxy proxy;
+ final String fileName = file.getName().toLowerCase(Locale.ROOT);
+ switch (fileName.contains(".") ? fileName.substring(fileName.lastIndexOf('.')) : "") {
+ case ".emf":
+ proxy = new EMFHandler();
+ break;
+ case ".wmf":
+ proxy = new WMFHandler();
+ break;
+ default:
+ proxy = new PPTHandler();
+ break;
+ }
+
+ proxy.parse(file);
+ return proxy;
+ }
+
+ private interface MFProxy extends Closeable {
+ void parse(File file) throws IOException;
+// boolean isEmpty();
+// void dumpRecords(Writer writer) throws IOException;
+// Iterable<HwmfEmbedded> getEmbeddings();
+ Dimension2D getSize();
+
+ default void setSlideNo(int slideNo) {}
+
+ String getTitle();
+ void draw(Graphics2D ctx);
+
+ default int getSlideCount() { return 1; }
+
+ default Set<Integer> slideIndexes(String range) {
+ return Collections.singleton(1);
+ }
+
+ GenericRecord getRoot();
+ }
+
+ /** Handler for ppt and pptx files */
+ private static class PPTHandler implements MFProxy {
+ SlideShow<?,?> ppt;
+ Slide<?,?> slide;
+
+ @Override
+ public void parse(File file) throws IOException {
+ ppt = SlideShowFactory.create(file, null, true);
+ slide = ppt.getSlides().get(0);
+ }
+
+ @Override
+ public Dimension2D getSize() {
+ return ppt.getPageSize();
+ }
+
+ @Override
+ public int getSlideCount() {
+ return ppt.getSlides().size();
+ }
+
+ @Override
+ public void setSlideNo(int slideNo) {
+ slide = ppt.getSlides().get(slideNo-1);
+ }
+
+ @Override
+ public String getTitle() {
+ return slide.getTitle();
+ }
+
+ private static final String RANGE_PATTERN = "(^|,)(?<from>\\d+)?(-(?<to>\\d+))?";
+
+ @Override
+ public Set<Integer> slideIndexes(String range) {
+ final Matcher matcher = Pattern.compile(RANGE_PATTERN).matcher(range);
+ Spliterator<Matcher> sp = new AbstractSpliterator<Matcher>(range.length(), ORDERED|NONNULL){
+ @Override
+ public boolean tryAdvance(Consumer<? super Matcher> action) {
+ boolean b = matcher.find();
+ if (b) {
+ action.accept(matcher);
}
- break;
+ return b;
}
+ };
+
+ return StreamSupport.stream(sp, false).
+ flatMap(this::range).
+ collect(Collectors.toCollection(TreeSet::new));
+ }
+
+ @Override
+ public void draw(Graphics2D ctx) {
+ slide.draw(ctx);
+ }
+
+ @Override
+ public void close() throws IOException {
+ if (ppt != null) {
+ ppt.close();
+ }
+ }
+
+ @Override
+ public GenericRecord getRoot() {
+ return (ppt instanceof GenericRecord) ? (GenericRecord)ppt : null;
+ }
+
+ private Stream<Integer> range(Matcher m) {
+ final int slideCount = ppt.getSlides().size();
+ String fromStr = m.group("from");
+ String toStr = m.group("to");
+ int from = (fromStr == null || fromStr.isEmpty() ? 1 : Integer.parseInt(fromStr));
+ int to = (toStr == null) ? from
+ : (toStr.isEmpty() || ((fromStr == null || fromStr.isEmpty()) && "1".equals(toStr))) ? slideCount
+ : Integer.parseInt(toStr);
+ return IntStream.rangeClosed(from, to).filter(i -> i <= slideCount).boxed();
+ }
+ }
+
+ private static class EMFHandler implements MFProxy {
+ private ImageRenderer imgr = null;
+ private InputStream is;
+
+ @Override
+ public void parse(File file) throws IOException {
+ imgr = DrawPictureShape.getImageRenderer(null, getContentType());
+ // stream needs to be kept open
+ is = file.toURI().toURL().openStream();
+ imgr.loadImage(is, getContentType());
+ }
+
+ protected String getContentType() {
+ return PictureData.PictureType.EMF.contentType;
+ }
+
+ @Override
+ public Dimension2D getSize() {
+ return imgr.getDimension();
+ }
+
+ @Override
+ public String getTitle() {
+ return "";
+ }
+
+ @Override
+ public void draw(Graphics2D ctx) {
+ Dimension2D dim = getSize();
+ imgr.drawImage(ctx, new Rectangle2D.Double(0, 0, dim.getWidth(), dim.getHeight()));
+ }
+
+ @Override
+ public void close() throws IOException {
+ if (is != null) {
+ try {
+ is.close();
+ } finally {
+ is = null;
}
}
}
- return slideIdx;
+
+ @Override
+ public GenericRecord getRoot() {
+ return imgr.getGenericRecord();
+ }
}
+
+ private static class WMFHandler extends EMFHandler {
+ @Override
+ protected String getContentType() {
+ return PictureData.PictureType.WMF.contentType;
+ }
+ }
+
}
Modified: poi/trunk/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestPPTX2PNG.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestPPTX2PNG.java?rev=1866808&r1=1866807&r2=1866808&view=diff
==============================================================================
--- poi/trunk/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestPPTX2PNG.java (original)
+++ poi/trunk/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestPPTX2PNG.java Wed Sep 11 21:24:06 2019
@@ -48,7 +48,7 @@ public class TestPPTX2PNG {
private static final String files =
"53446.ppt, alterman_security.ppt, alterman_security.pptx, KEY02.pptx, themes.pptx, " +
"backgrounds.pptx, layouts.pptx, sample.pptx, shapes.pptx, 54880_chinese.ppt, keyframes.pptx," +
- "customGeo.pptx, customGeo.ppt";
+ "customGeo.pptx, customGeo.ppt, wrench.emf, santa.wmf";
@@ -83,8 +83,12 @@ public class TestPPTX2PNG {
"-slide", "-1", // -1 for all
"-outdir", new File("build/tmp/").getCanonicalPath(),
"-outpat", "${basename}-${slideno}-${ext}.${format}",
- "-scale", "1.333333333",
+ // "-dump", new File("build/tmp/", pptFile+".dump").getCanonicalPath(),
+ "-dump", "null",
"-quiet",
+ "-fixside", "long",
+ "-scale", "800",
+ // "-scale", "1.333333333",
(basedir == null ? samples.getFile(pptFile) : new File(basedir, pptFile)).getAbsolutePath()
};
PPTX2PNG.main(args);
Modified: poi/trunk/src/scratchpad/src/org/apache/poi/hemf/draw/HemfImageRenderer.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/src/org/apache/poi/hemf/draw/HemfImageRenderer.java?rev=1866808&r1=1866807&r2=1866808&view=diff
==============================================================================
--- poi/trunk/src/scratchpad/src/org/apache/poi/hemf/draw/HemfImageRenderer.java (original)
+++ poi/trunk/src/scratchpad/src/org/apache/poi/hemf/draw/HemfImageRenderer.java Wed Sep 11 21:24:06 2019
@@ -24,11 +24,11 @@ import java.awt.RenderingHints;
import java.awt.geom.Dimension2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
-import java.awt.image.RescaleOp;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
+import org.apache.poi.common.usermodel.GenericRecord;
import org.apache.poi.hemf.usermodel.HemfPicture;
import org.apache.poi.sl.draw.BitmapImageRenderer;
import org.apache.poi.sl.draw.ImageRenderer;
@@ -109,4 +109,8 @@ public class HemfImageRenderer implement
}
}
+ @Override
+ public GenericRecord getGenericRecord() {
+ return image;
+ }
}
Modified: poi/trunk/src/scratchpad/src/org/apache/poi/hemf/record/emf/HemfComment.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/src/org/apache/poi/hemf/record/emf/HemfComment.java?rev=1866808&r1=1866807&r2=1866808&view=diff
==============================================================================
--- poi/trunk/src/scratchpad/src/org/apache/poi/hemf/record/emf/HemfComment.java (original)
+++ poi/trunk/src/scratchpad/src/org/apache/poi/hemf/record/emf/HemfComment.java Wed Sep 11 21:24:06 2019
@@ -24,12 +24,16 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
+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.record.emfplus.HemfPlusRecord;
import org.apache.poi.hemf.record.emfplus.HemfPlusRecordIterator;
import org.apache.poi.hwmf.usermodel.HwmfPicture;
+import org.apache.poi.util.GenericRecordJsonWriter;
+import org.apache.poi.util.GenericRecordUtil;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.Internal;
import org.apache.poi.util.LittleEndianConsts;
@@ -78,10 +82,15 @@ public class HemfComment {
}
}
- public interface EmfCommentData {
+ public interface EmfCommentData extends GenericRecord {
HemfCommentRecordType getCommentRecordType();
long init(LittleEndianInputStream leis, long dataSize) throws IOException;
+
+ @Override
+ default Enum getGenericRecordType() {
+ return getCommentRecordType();
+ }
}
public static class EmfComment implements HemfRecord {
@@ -116,7 +125,12 @@ public class HemfComment {
@Override
public String toString() {
- return "{ data: "+data+" }";
+ return GenericRecordJsonWriter.marshal(this);
+ }
+
+ @Override
+ public Map<String, Supplier<?>> getGenericProperties() {
+ return GenericRecordUtil.getGenericProperties("data", this::getCommentData);
}
}
@@ -241,7 +255,19 @@ public class HemfComment {
@Override
public String toString() {
- return "\""+new String(privateData, LocaleUtil.CHARSET_1252).replaceAll("\\p{Cntrl}", ".")+"\"";
+ return GenericRecordJsonWriter.marshal(this);
+ }
+
+ public String getPrivateDataAsString() {
+ return new String(privateData, LocaleUtil.CHARSET_1252);
+ }
+
+ @Override
+ public Map<String, Supplier<?>> getGenericProperties() {
+ return GenericRecordUtil.getGenericProperties(
+ "privateData", this::getPrivateData,
+ "privateDataAsString", this::getPrivateDataAsString
+ );
}
}
@@ -271,6 +297,16 @@ public class HemfComment {
public void draw(HemfGraphics ctx) {
records.forEach(ctx::draw);
}
+
+ @Override
+ public Map<String, Supplier<?>> getGenericProperties() {
+ return null;
+ }
+
+ @Override
+ public List<HemfPlusRecord> getGenericChildren() {
+ return getRecords();
+ }
}
public static class EmfCommentDataBeginGroup implements EmfCommentData {
@@ -301,6 +337,22 @@ public class HemfComment {
return leis.getReadIndex()-startIdx;
}
+
+ public Rectangle2D getBounds() {
+ return bounds;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ @Override
+ public Map<String, Supplier<?>> getGenericProperties() {
+ return GenericRecordUtil.getGenericProperties(
+ "bounds", this::getBounds,
+ "description", this::getDescription
+ );
+ }
}
public static class EmfCommentDataEndGroup implements EmfCommentData {
@@ -319,6 +371,11 @@ public class HemfComment {
assert(publicCommentIdentifier == HemfCommentRecordType.emfEndGroup.id);
return leis.getReadIndex()-startIdx;
}
+
+ @Override
+ public Map<String, Supplier<?>> getGenericProperties() {
+ return null;
+ }
}
public static class EmfCommentDataMultiformats implements EmfCommentData {
@@ -369,6 +426,20 @@ public class HemfComment {
public List<EmfCommentDataFormat> getFormats() {
return Collections.unmodifiableList(formats);
}
+
+ public Rectangle2D getBounds() {
+ return bounds;
+ }
+
+ @Override
+ public Map<String, Supplier<?>> getGenericProperties() {
+ return GenericRecordUtil.getGenericProperties("bounds", this::getBounds);
+ }
+
+ @Override
+ public List<EmfCommentDataFormat> getGenericChildren() {
+ return getFormats();
+ }
}
public enum EmfFormatSignature {
@@ -400,7 +471,7 @@ public class HemfComment {
}
- public static class EmfCommentDataFormat {
+ public static class EmfCommentDataFormat implements GenericRecord {
private EmfFormatSignature signature;
private int version;
private int sizeData;
@@ -439,11 +510,20 @@ public class HemfComment {
public EmfFormatSignature getSignature() {
return signature;
}
+
+ @Override
+ public Map<String, Supplier<?>> getGenericProperties() {
+ return GenericRecordUtil.getGenericProperties(
+ "signature", this::getSignature,
+ "version", () -> version,
+ "sizeData", () -> sizeData,
+ "offData", () -> offData
+ );
+ }
}
public static class EmfCommentDataWMF implements EmfCommentData {
private final Rectangle2D bounds = new Rectangle2D.Double();
- private final List<EmfCommentDataFormat> formats = new ArrayList<>();
private byte[] wmfData;
@Override
public HemfCommentRecordType getCommentRecordType() {
@@ -485,12 +565,21 @@ public class HemfComment {
public byte[] getWMFData() {
return wmfData;
}
+
+ public Rectangle2D getBounds() {
+ return bounds;
+ }
+
+ @Override
+ public Map<String, Supplier<?>> getGenericProperties() {
+ return GenericRecordUtil.getGenericProperties(
+ "bounds", this::getBounds,
+ "wmfData", this::getWMFData
+ );
+ }
}
public static class EmfCommentDataUnicode implements EmfCommentData {
- private final Rectangle2D bounds = new Rectangle2D.Double();
- private final List<EmfCommentDataFormat> formats = new ArrayList<>();
-
@Override
public HemfCommentRecordType getCommentRecordType() {
return HemfCommentRecordType.emfUnicodeString;
@@ -501,5 +590,10 @@ public class HemfComment {
throws IOException {
throw new RecordFormatException("UNICODE_STRING/UNICODE_END values are reserved in CommentPublic records");
}
+
+ @Override
+ public Map<String, Supplier<?>> getGenericProperties() {
+ return null;
+ }
}
}
Modified: poi/trunk/src/scratchpad/src/org/apache/poi/hemf/record/emf/HemfDraw.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/src/org/apache/poi/hemf/record/emf/HemfDraw.java?rev=1866808&r1=1866807&r2=1866808&view=diff
==============================================================================
--- poi/trunk/src/scratchpad/src/org/apache/poi/hemf/record/emf/HemfDraw.java (original)
+++ poi/trunk/src/scratchpad/src/org/apache/poi/hemf/record/emf/HemfDraw.java Wed Sep 11 21:24:06 2019
@@ -17,11 +17,10 @@
package org.apache.poi.hemf.record.emf;
-import static org.apache.poi.hwmf.record.HwmfDraw.boundsToString;
import static org.apache.poi.hwmf.record.HwmfDraw.normalizeBounds;
+import static org.apache.poi.util.GenericRecordUtil.getBitsAsString;
import java.awt.Shape;
-import java.awt.geom.AffineTransform;
import java.awt.geom.Arc2D;
import java.awt.geom.Dimension2D;
import java.awt.geom.Path2D;
@@ -29,13 +28,17 @@ import java.awt.geom.PathIterator;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.io.IOException;
+import java.util.Map;
+import java.util.function.Supplier;
+import java.util.stream.IntStream;
import org.apache.poi.hemf.draw.HemfDrawProperties;
import org.apache.poi.hemf.draw.HemfGraphics;
import org.apache.poi.hwmf.draw.HwmfGraphics.FillDrawStyle;
import org.apache.poi.hwmf.record.HwmfDraw;
import org.apache.poi.hwmf.record.HwmfDraw.WmfSelectObject;
-import org.apache.poi.util.Internal;
+import org.apache.poi.util.GenericRecordJsonWriter;
+import org.apache.poi.util.GenericRecordUtil;
import org.apache.poi.util.LittleEndianConsts;
import org.apache.poi.util.LittleEndianInputStream;
@@ -47,26 +50,30 @@ public class HemfDraw {
*/
public static class EmfSelectObject extends WmfSelectObject implements HemfRecord {
- private static final String[] STOCK_IDS = {
- "0x80000000 /* WHITE_BRUSH */",
- "0x80000001 /* LTGRAY_BRUSH */",
- "0x80000002 /* GRAY_BRUSH */",
- "0x80000003 /* DKGRAY_BRUSH */",
- "0x80000004 /* BLACK_BRUSH */",
- "0x80000005 /* NULL_BRUSH */",
- "0x80000006 /* WHITE_PEN */",
- "0x80000007 /* BLACK_PEN */",
- "0x80000008 /* NULL_PEN */",
- "0x8000000A /* OEM_FIXED_FONT */",
- "0x8000000B /* ANSI_FIXED_FONT */",
- "0x8000000C /* ANSI_VAR_FONT */",
- "0x8000000D /* SYSTEM_FONT */",
- "0x8000000E /* DEVICE_DEFAULT_FONT */",
- "0x8000000F /* DEFAULT_PALETTE */",
- "0x80000010 /* SYSTEM_FIXED_FONT */",
- "0x80000011 /* DEFAULT_GUI_FONT */",
- "0x80000012 /* DC_BRUSH */",
- "0x80000013 /* DC_PEN */"
+ private static final int[] IDX_MASKS = IntStream.rangeClosed(0x80000000,0x80000013).toArray();
+
+ private static final String[] IDX_NAMES = {
+ "WHITE_BRUSH",
+ "LTGRAY_BRUSH",
+ "GRAY_BRUSH",
+ "DKGRAY_BRUSH",
+ "BLACK_BRUSH",
+ "NULL_BRUSH",
+ "WHITE_PEN",
+ "BLACK_PEN",
+ "NULL_PEN",
+ // 0x80000009 is not a valid stock object
+ "INVALID",
+ "OEM_FIXED_FONT",
+ "ANSI_FIXED_FONT",
+ "ANSI_VAR_FONT",
+ "SYSTEM_FONT",
+ "DEVICE_DEFAULT_FONT",
+ "DEFAULT_PALETTE",
+ "SYSTEM_FIXED_FONT",
+ "DEFAULT_GUI_FONT",
+ "DC_BRUSH",
+ "DC_PEN"
};
@Override
@@ -84,12 +91,20 @@ public class HemfDraw {
@Override
public String toString() {
- return "{ index: "+
- (((objectIndex & 0x80000000) != 0 && (objectIndex & 0x3FFFFFFF) <= 13 )
- ? STOCK_IDS[objectIndex & 0x3FFFFFFF]
- : objectIndex)+" }";
+ return GenericRecordJsonWriter.marshal(this);
}
+ @Override
+ public Map<String, Supplier<?>> getGenericProperties() {
+ return GenericRecordUtil.getGenericProperties(
+ "objectIndex", getBitsAsString(this::getObjectIndex, IDX_MASKS, IDX_NAMES)
+ );
+ }
+
+ @Override
+ public Enum getGenericRecordType() {
+ return getEmfRecordType();
+ }
}
@@ -183,6 +198,23 @@ public class HemfDraw {
public void draw(HemfGraphics ctx) {
ctx.draw(path -> path.append(poly, !hasStartPoint()), getFillDrawStyle());
}
+
+ public Rectangle2D getBounds() {
+ return bounds;
+ }
+
+ @Override
+ public Map<String, Supplier<?>> getGenericProperties() {
+ return GenericRecordUtil.getGenericProperties(
+ "base", super::getGenericProperties,
+ "bounds", this::getBounds
+ );
+ }
+
+ @Override
+ public Enum getGenericRecordType() {
+ return getEmfRecordType();
+ }
}
/**
@@ -267,6 +299,23 @@ public class HemfDraw {
public void draw(HemfGraphics ctx) {
ctx.draw(path -> path.append(poly, false), getFillDrawStyle());
}
+
+ public Rectangle2D getBounds() {
+ return bounds;
+ }
+
+ @Override
+ public Map<String, Supplier<?>> getGenericProperties() {
+ return GenericRecordUtil.getGenericProperties(
+ "base", super::getGenericProperties,
+ "bounds", this::getBounds
+ );
+ }
+
+ @Override
+ public Enum getGenericRecordType() {
+ return getEmfRecordType();
+ }
}
/**
@@ -429,10 +478,8 @@ public class HemfDraw {
Point2D pnt = new Point2D.Double();
for (long nPoints : polygonPointCount) {
- /**
- * An array of WMF PointL objects that specifies the points for all polygons in logical units.
- * The number of points is specified by the Count field value.
- */
+ // An array of WMF PointL objects that specifies the points for all polygons in logical units.
+ // The number of points is specified by the Count field value.
Path2D poly = new Path2D.Double(Path2D.WIND_EVEN_ODD, (int)nPoints);
for (int i=0; i<nPoints; i++) {
size += readPoint(leis, pnt);
@@ -460,6 +507,23 @@ public class HemfDraw {
ctx.draw(path -> path.append(shape, false), getFillDrawStyle());
}
+
+ public Rectangle2D getBounds() {
+ return bounds;
+ }
+
+ @Override
+ public Map<String, Supplier<?>> getGenericProperties() {
+ return GenericRecordUtil.getGenericProperties(
+ "base", super::getGenericProperties,
+ "bounds", this::getBounds
+ );
+ }
+
+ @Override
+ public Enum getGenericRecordType() {
+ return getEmfRecordType();
+ }
}
/**
@@ -527,6 +591,11 @@ public class HemfDraw {
size += colorRef.init(leis);
return size;
}
+
+ @Override
+ public Enum getGenericRecordType() {
+ return getEmfRecordType();
+ }
}
/**
@@ -547,6 +616,11 @@ public class HemfDraw {
public void draw(final HemfGraphics ctx) {
ctx.draw((path) -> path.moveTo(point.getX(), point.getY()), FillDrawStyle.NONE);
}
+
+ @Override
+ public Enum getGenericRecordType() {
+ return getEmfRecordType();
+ }
}
/**
@@ -571,6 +645,11 @@ public class HemfDraw {
public void draw(HemfGraphics ctx) {
ctx.draw(path -> path.append(getShape(), false), getFillDrawStyle());
}
+
+ @Override
+ public Enum getGenericRecordType() {
+ return getEmfRecordType();
+ }
}
/**
@@ -596,6 +675,11 @@ public class HemfDraw {
public void draw(HemfGraphics ctx) {
ctx.draw(path -> path.append(getShape(), false), getFillDrawStyle());
}
+
+ @Override
+ public Enum getGenericRecordType() {
+ return getEmfRecordType();
+ }
}
/**
@@ -620,6 +704,11 @@ public class HemfDraw {
public void draw(HemfGraphics ctx) {
ctx.draw(path -> path.append(getShape(), false), getFillDrawStyle());
}
+
+ @Override
+ public Enum getGenericRecordType() {
+ return getEmfRecordType();
+ }
}
/**
@@ -642,6 +731,11 @@ public class HemfDraw {
public void draw(HemfGraphics ctx) {
ctx.draw(path -> path.append(getShape(), false), FillDrawStyle.FILL_DRAW);
}
+
+ @Override
+ public Enum getGenericRecordType() {
+ return getEmfRecordType();
+ }
}
/**
@@ -663,6 +757,11 @@ public class HemfDraw {
public void draw(HemfGraphics ctx) {
ctx.draw(path -> path.append(normalizeBounds(bounds), false), FillDrawStyle.FILL_DRAW);
}
+
+ @Override
+ public Enum getGenericRecordType() {
+ return getEmfRecordType();
+ }
}
/**
@@ -680,8 +779,9 @@ public class HemfDraw {
long size = readRectL(leis, bounds);
// A 32-bit unsigned integer that defines the x-coordinate of the point.
- width = (int)leis.readUInt();
- height = (int)leis.readUInt();
+ int width = (int)leis.readUInt();
+ int height = (int)leis.readUInt();
+ corners.setSize(width, height);
return size + 2*LittleEndianConsts.INT_SIZE;
}
@@ -690,6 +790,11 @@ public class HemfDraw {
public void draw(HemfGraphics ctx) {
ctx.draw(path -> path.append(getShape(), false), FillDrawStyle.FILL_DRAW);
}
+
+ @Override
+ public Enum getGenericRecordType() {
+ return getEmfRecordType();
+ }
}
/**
@@ -711,6 +816,11 @@ public class HemfDraw {
public void draw(final HemfGraphics ctx) {
ctx.draw((path) -> path.lineTo(point.getX(), point.getY()), FillDrawStyle.DRAW);
}
+
+ @Override
+ public Enum getGenericRecordType() {
+ return getEmfRecordType();
+ }
}
/**
@@ -736,6 +846,11 @@ public class HemfDraw {
final Arc2D arc = getShape();
ctx.draw((path) -> path.append(arc, true), getFillDrawStyle());
}
+
+ @Override
+ public Enum getGenericRecordType() {
+ return getEmfRecordType();
+ }
}
/** The EMR_POLYDRAW record specifies a set of line segments and Bezier curves. */
@@ -829,6 +944,23 @@ public class HemfDraw {
public void draw(HemfGraphics ctx) {
ctx.draw(path -> path.append(poly, false), getFillDrawStyle());
}
+
+ public Rectangle2D getBounds() {
+ return bounds;
+ }
+
+ @Override
+ public Map<String, Supplier<?>> getGenericProperties() {
+ return GenericRecordUtil.getGenericProperties(
+ "base", super::getGenericProperties,
+ "bounds", this::getBounds
+ );
+ }
+
+ @Override
+ public Enum getGenericRecordType() {
+ return getEmfRecordType();
+ }
}
public static class EmfPolyDraw16 extends EmfPolyDraw {
@@ -852,7 +984,7 @@ public class HemfDraw {
* When an application processes the EMR_BEGINPATH record, all previous paths
* MUST be discarded from the playback device context.
*/
- public static class EmfBeginPath implements HemfRecord {
+ public static class EmfBeginPath implements HemfRecordWithoutProperties {
@Override
public HemfRecordType getEmfRecordType() {
return HemfRecordType.beginPath;
@@ -880,7 +1012,7 @@ public class HemfDraw {
* This record closes a path bracket and selects the path defined by the bracket into
* the playback device context.
*/
- public static class EmfEndPath implements HemfRecord {
+ public static class EmfEndPath implements HemfRecordWithoutProperties {
@Override
public HemfRecordType getEmfRecordType() {
return HemfRecordType.endPath;
@@ -906,7 +1038,7 @@ public class HemfDraw {
/**
* This record aborts a path bracket or discards the path from a closed path bracket.
*/
- public static class EmfAbortPath implements HemfRecord {
+ public static class EmfAbortPath implements HemfRecordWithoutProperties {
@Override
public HemfRecordType getEmfRecordType() {
return HemfRecordType.abortPath;
@@ -949,7 +1081,7 @@ public class HemfDraw {
* After processing the EMR_CLOSEFIGURE record, adding a line or curve to the path
* MUST start a new figure.
*/
- public static class EmfCloseFigure implements HemfRecord {
+ public static class EmfCloseFigure implements HemfRecordWithoutProperties {
@Override
public HemfRecordType getEmfRecordType() {
return HemfRecordType.closeFigure;
@@ -980,7 +1112,7 @@ public class HemfDraw {
* This record transforms any curves in the selected path into the playback device
* context; each curve MUST be turned into a sequence of lines.
*/
- public static class EmfFlattenPath implements HemfRecord {
+ public static class EmfFlattenPath implements HemfRecordWithoutProperties {
@Override
public HemfRecordType getEmfRecordType() {
return HemfRecordType.flattenPath;
@@ -996,7 +1128,7 @@ public class HemfDraw {
* This record redefines the current path as the area that would be painted if the path
* were drawn using the pen currently selected into the playback device context.
*/
- public static class EmfWidenPath implements HemfRecord {
+ public static class EmfWidenPath implements HemfRecordWithoutProperties {
@Override
public HemfRecordType getEmfRecordType() {
return HemfRecordType.widenPath;
@@ -1040,7 +1172,16 @@ public class HemfDraw {
@Override
public String toString() {
- return boundsToString(bounds);
+ return GenericRecordJsonWriter.marshal(this);
+ }
+
+ public Rectangle2D getBounds() {
+ return bounds;
+ }
+
+ @Override
+ public Map<String, Supplier<?>> getGenericProperties() {
+ return GenericRecordUtil.getGenericProperties("bounds", this::getBounds);
}
}
@@ -1155,16 +1296,4 @@ public class HemfDraw {
ctx.draw((path) -> path.append(pi, true), fillDrawStyle);
}
-
-
- @Internal
- public static String xformToString(AffineTransform xForm) {
- return (xForm == null) ? "null" :
- "{ scaleX: "+xForm.getScaleX()+
- ", shearX: "+xForm.getShearX()+
- ", transX: "+xForm.getTranslateX()+
- ", scaleY: "+xForm.getScaleY()+
- ", shearY: "+xForm.getShearY()+
- ", transY: "+xForm.getTranslateY()+" }";
- }
}
Modified: poi/trunk/src/scratchpad/src/org/apache/poi/hemf/record/emf/HemfFill.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/src/org/apache/poi/hemf/record/emf/HemfFill.java?rev=1866808&r1=1866807&r2=1866808&view=diff
==============================================================================
--- poi/trunk/src/scratchpad/src/org/apache/poi/hemf/record/emf/HemfFill.java (original)
+++ poi/trunk/src/scratchpad/src/org/apache/poi/hemf/record/emf/HemfFill.java Wed Sep 11 21:24:06 2019
@@ -19,10 +19,7 @@ package org.apache.poi.hemf.record.emf;
import static org.apache.poi.hemf.record.emf.HemfDraw.readPointL;
import static org.apache.poi.hemf.record.emf.HemfDraw.readRectL;
-import static org.apache.poi.hemf.record.emf.HemfDraw.xformToString;
import static org.apache.poi.hemf.record.emf.HemfRecordIterator.HEADER_SIZE;
-import static org.apache.poi.hwmf.record.HwmfDraw.boundsToString;
-import static org.apache.poi.hwmf.record.HwmfDraw.pointToString;
import java.awt.Shape;
import java.awt.geom.AffineTransform;
@@ -33,7 +30,11 @@ import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;
+import java.util.Collections;
+import java.util.LinkedHashMap;
import java.util.List;
+import java.util.Map;
+import java.util.function.Supplier;
import org.apache.poi.hemf.draw.HemfDrawProperties;
import org.apache.poi.hemf.draw.HemfGraphics;
@@ -45,6 +46,8 @@ import org.apache.poi.hwmf.record.HwmfFi
import org.apache.poi.hwmf.record.HwmfFill.ColorUsage;
import org.apache.poi.hwmf.record.HwmfRegionMode;
import org.apache.poi.hwmf.record.HwmfTernaryRasterOp;
+import org.apache.poi.util.GenericRecordJsonWriter;
+import org.apache.poi.util.GenericRecordUtil;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.LittleEndianConsts;
@@ -70,6 +73,11 @@ public class HemfFill {
polyFillMode = HwmfPolyfillMode.valueOf((int)leis.readUInt());
return LittleEndianConsts.INT_SIZE;
}
+
+ @Override
+ public Enum getGenericRecordType() {
+ return getEmfRecordType();
+ }
}
public static class EmfExtFloodFill extends HwmfFill.WmfExtFloodFill implements HemfRecord {
@@ -85,9 +93,14 @@ public class HemfFill {
size += colorRef.init(leis);
// A 32-bit unsigned integer that specifies how to use the Color value to determine the area for
// the flood fill operation. The value MUST be in the FloodFill enumeration
- mode = (int)leis.readUInt();
+ mode = HwmfFloodFillMode.values()[(int)leis.readUInt()];
return size + LittleEndianConsts.INT_SIZE;
}
+
+ @Override
+ public Enum getGenericRecordType() {
+ return getEmfRecordType();
+ }
}
/**
@@ -185,11 +198,34 @@ public class HemfFill {
@Override
public String toString() {
- return
- "{ bounds: "+boundsToString(bounds)+
- ", xFormSrc: " + xformToString(xFormSrc) +
- ", bkColorSrc: "+bkColorSrc+
- ","+super.toString().substring(1);
+ return GenericRecordJsonWriter.marshal(this);
+ }
+
+ public Rectangle2D getBounds() {
+ return bounds;
+ }
+
+ public AffineTransform getXFormSrc() {
+ return xFormSrc;
+ }
+
+ public HwmfColorRef getBkColorSrc() {
+ return bkColorSrc;
+ }
+
+ @Override
+ public Map<String, Supplier<?>> getGenericProperties() {
+ return GenericRecordUtil.getGenericProperties(
+ "base", super::getGenericProperties,
+ "bounds", this::getBounds,
+ "xFormSrc", this::getXFormSrc,
+ "bkColorSrc", this::getBkColorSrc
+ );
+ }
+
+ @Override
+ public Enum getGenericRecordType() {
+ return getEmfRecordType();
}
}
@@ -259,6 +295,23 @@ public class HemfFill {
return size;
}
+
+ public Rectangle2D getBounds() {
+ return bounds;
+ }
+
+ @Override
+ public Map<String, Supplier<?>> getGenericProperties() {
+ return GenericRecordUtil.getGenericProperties(
+ "base", super::getGenericProperties,
+ "bounds", this::getBounds
+ );
+ }
+
+ @Override
+ public Enum getGenericRecordType() {
+ return getEmfRecordType();
+ }
}
/**
@@ -296,9 +349,10 @@ public class HemfFill {
// A 32-bit unsigned integer that specifies the brush EMF Object Table index.
brushIndex = (int)leis.readUInt();
// A 32-bit signed integer that specifies the width of the vertical brush stroke, in logical units.
- width = leis.readInt();
+ int width = leis.readInt();
// A 32-bit signed integer that specifies the height of the horizontal brush stroke, in logical units.
- height = leis.readInt();
+ int height = leis.readInt();
+ frame.setSize(width,height);
size += 4*LittleEndianConsts.INT_SIZE;
size += readRgnData(leis, rgnRects);
return size;
@@ -313,6 +367,28 @@ public class HemfFill {
protected Shape getShape() {
return getRgnShape(rgnRects);
}
+
+ public Rectangle2D getBounds() {
+ return bounds;
+ }
+
+ public List<Rectangle2D> getRgnRects() {
+ return rgnRects;
+ }
+
+ @Override
+ public Map<String, Supplier<?>> getGenericProperties() {
+ return GenericRecordUtil.getGenericProperties(
+ "base", super::getGenericProperties,
+ "bounds", this::getBounds,
+ "rgnRects", this::getRgnRects
+ );
+ }
+
+ @Override
+ public Enum getGenericRecordType() {
+ return getEmfRecordType();
+ }
}
/** The EMR_INVERTRGN record inverts the colors in the specified region. */
@@ -338,6 +414,22 @@ public class HemfFill {
protected Shape getShape() {
return getRgnShape(rgnRects);
}
+
+ public Rectangle2D getBounds() {
+ return bounds;
+ }
+
+ public List<Rectangle2D> getRgnRects() {
+ return rgnRects;
+ }
+
+ @Override
+ public Map<String, Supplier<?>> getGenericProperties() {
+ return GenericRecordUtil.getGenericProperties(
+ "bounds", this::getBounds,
+ "rgnRects", this::getRgnRects
+ );
+ }
}
/**
@@ -375,6 +467,28 @@ public class HemfFill {
protected Shape getShape() {
return getRgnShape(rgnRects);
}
+
+ public Rectangle2D getBounds() {
+ return bounds;
+ }
+
+ public List<Rectangle2D> getRgnRects() {
+ return rgnRects;
+ }
+
+ @Override
+ public Map<String, Supplier<?>> getGenericProperties() {
+ return GenericRecordUtil.getGenericProperties(
+ "base", super::getGenericProperties,
+ "bounds", this::getBounds,
+ "rgnRects", this::getRgnRects
+ );
+ }
+
+ @Override
+ public Enum getGenericRecordType() {
+ return getEmfRecordType();
+ }
}
public static class EmfExtSelectClipRgn implements HemfRecord {
@@ -414,19 +528,23 @@ public class HemfFill {
@Override
public String toString() {
- StringBuilder sb = new StringBuilder();
- sb.append("{ regionMode: '"+regionMode+"'");
- sb.append(", regions: [");
- boolean isFirst = true;
- for (Rectangle2D r : rgnRects) {
- if (!isFirst) {
- sb.append(",");
- }
- isFirst = false;
- sb.append(boundsToString(r));
- }
- sb.append("]}");
- return sb.toString();
+ return GenericRecordJsonWriter.marshal(this);
+ }
+
+ public HwmfRegionMode getRegionMode() {
+ return regionMode;
+ }
+
+ public List<Rectangle2D> getRgnRects() {
+ return rgnRects;
+ }
+
+ @Override
+ public Map<String, Supplier<?>> getGenericProperties() {
+ return GenericRecordUtil.getGenericProperties(
+ "regionMode", this::getRegionMode,
+ "rgnRects", this::getRgnRects
+ );
}
}
@@ -539,6 +657,23 @@ public class HemfFill {
return size;
}
+
+ @Override
+ public Map<String, Supplier<?>> getGenericProperties() {
+ final Map<String,Supplier<?>> m = new LinkedHashMap<>();
+ m.put("bounds", () -> bounds);
+ m.put("destRect", () -> destRect);
+ m.put("srcRect", () -> srcRect);
+ m.put("blendOperation", () -> blendOperation);
+ m.put("blendFlags", () -> blendFlags);
+ m.put("srcConstantAlpha", () -> srcConstantAlpha);
+ m.put("alphaFormat", () -> alphaFormat);
+ m.put("xFormSrc", () -> xFormSrc);
+ m.put("bkColorSrc", () -> bkColorSrc);
+ m.put("usageSrc", () -> usageSrc);
+ m.put("bitmap", () -> bitmap);
+ return Collections.unmodifiableMap(m);
+ }
}
/**
@@ -591,15 +726,40 @@ public class HemfFill {
return size;
}
+ public Rectangle2D getBounds() {
+ return bounds;
+ }
+
+ public Point2D getDest() {
+ return dest;
+ }
+
+ public Rectangle2D getSrc() {
+ return src;
+ }
+
+ public ColorUsage getUsageSrc() {
+ return usageSrc;
+ }
+
+ public HwmfBitmapDib getBitmap() {
+ return bitmap;
+ }
+
@Override
public String toString() {
- return
- "{ bounds: " + boundsToString(bounds) +
- ", dest: " + pointToString(dest) +
- ", src: " + boundsToString(src) +
- ", usageSrc: '" + usageSrc + "'" +
- ", bitmap: " + bitmap +
- "}";
+ return GenericRecordJsonWriter.marshal(this);
+ }
+
+ @Override
+ public Map<String, Supplier<?>> getGenericProperties() {
+ return GenericRecordUtil.getGenericProperties(
+ "bounds", this::getBounds,
+ "dest", this::getDest,
+ "src", this::getSrc,
+ "usageSrc", this::getUsageSrc,
+ "bitmap", this::getBitmap
+ );
}
}
@@ -670,9 +830,7 @@ public class HemfFill {
static int readBounds2(LittleEndianInputStream leis, Rectangle2D bounds) {
- /**
- * The 32-bit signed integers that defines the corners of the bounding rectangle.
- */
+ // The 32-bit signed integers that defines the corners of the bounding rectangle.
int x = leis.readInt();
int y = leis.readInt();
int w = leis.readInt();
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@poi.apache.org
For additional commands, e-mail: commits-help@poi.apache.org