aboutsummaryrefslogtreecommitdiffstats
path: root/src/ooxml
diff options
context:
space:
mode:
authorAndreas Beeker <kiwiwings@apache.org>2020-12-17 23:42:26 +0000
committerAndreas Beeker <kiwiwings@apache.org>2020-12-17 23:42:26 +0000
commitbfade7c591a7ddb8eda643e4fb4932f7f8bad6a4 (patch)
tree20fe19f553260c1a08c7b1b41fa76359cca5576e /src/ooxml
parentfcc808d17db2c61e9f4d472ef07b3c4468eb6da6 (diff)
downloadpoi-bfade7c591a7ddb8eda643e4fb4932f7f8bad6a4.tar.gz
poi-bfade7c591a7ddb8eda643e4fb4932f7f8bad6a4.zip
#64876 - Unable to convert pptx to pdf
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1884578 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'src/ooxml')
-rw-r--r--src/ooxml/java/org/apache/poi/xdgf/usermodel/XDGFShape.java8
-rw-r--r--src/ooxml/java/org/apache/poi/xslf/util/DummyFormat.java49
-rw-r--r--src/ooxml/java/org/apache/poi/xslf/util/DummyGraphics2d.java1029
-rw-r--r--src/ooxml/java/org/apache/poi/xslf/util/PPTX2PNG.java6
-rw-r--r--src/ooxml/testcases/org/apache/poi/xslf/TestXSLFBugs.java86
5 files changed, 1166 insertions, 12 deletions
diff --git a/src/ooxml/java/org/apache/poi/xdgf/usermodel/XDGFShape.java b/src/ooxml/java/org/apache/poi/xdgf/usermodel/XDGFShape.java
index 0427817fdd..2f22ab805f 100644
--- a/src/ooxml/java/org/apache/poi/xdgf/usermodel/XDGFShape.java
+++ b/src/ooxml/java/org/apache/poi/xdgf/usermodel/XDGFShape.java
@@ -28,6 +28,8 @@ import java.util.Collection;
import java.util.List;
import java.util.Map.Entry;
+import com.microsoft.schemas.office.visio.x2012.main.ShapeSheetType;
+import com.microsoft.schemas.office.visio.x2012.main.TextType;
import org.apache.poi.ooxml.POIXMLException;
import org.apache.poi.util.Internal;
import org.apache.poi.xdgf.exceptions.XDGFException;
@@ -37,9 +39,6 @@ import org.apache.poi.xdgf.usermodel.section.XDGFSection;
import org.apache.poi.xdgf.usermodel.shape.ShapeVisitor;
import org.apache.poi.xdgf.usermodel.shape.exceptions.StopVisitingThisBranch;
-import com.microsoft.schemas.office.visio.x2012.main.ShapeSheetType;
-import com.microsoft.schemas.office.visio.x2012.main.TextType;
-
/**
* A shape is a collection of Geometry Visualization, Format, Text, Images, and
* Shape Data in a Drawing Page.
@@ -723,7 +722,6 @@ public class XDGFShape extends XDGFSheet {
float lineWeight = getLineWeight().floatValue();
int cap;
int join = BasicStroke.JOIN_MITER;
- float miterlimit = 10.0f;
switch (getLineCap()) {
case 0:
@@ -826,7 +824,7 @@ public class XDGFShape extends XDGFSheet {
}
}
- return new BasicStroke(lineWeight, cap, join, miterlimit, dash, 0);
+ return new BasicStroke(lineWeight, cap, join, 10, dash, 0);
}
//
diff --git a/src/ooxml/java/org/apache/poi/xslf/util/DummyFormat.java b/src/ooxml/java/org/apache/poi/xslf/util/DummyFormat.java
new file mode 100644
index 0000000000..8079ac9acb
--- /dev/null
+++ b/src/ooxml/java/org/apache/poi/xslf/util/DummyFormat.java
@@ -0,0 +1,49 @@
+package org.apache.poi.xslf.util;
+
+import java.awt.Graphics2D;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.io.UnsupportedEncodingException;
+import java.nio.charset.StandardCharsets;
+
+public class DummyFormat implements OutputFormat {
+
+ private final ByteArrayOutputStream bos;
+ private final DummyGraphics2d dummy2d;
+
+ public DummyFormat() {
+ try {
+ bos = new ByteArrayOutputStream();
+ dummy2d = new DummyGraphics2d(new PrintStream(bos, true, StandardCharsets.UTF_8.name()));
+ } catch (UnsupportedEncodingException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public Graphics2D addSlide(double width, double height) throws IOException {
+ bos.reset();
+ return dummy2d;
+ }
+
+ @Override
+ public void writeSlide(MFProxy proxy, File outFile) throws IOException {
+ try (FileOutputStream fos = new FileOutputStream(outFile)) {
+ bos.writeTo(fos);
+ bos.reset();
+ }
+ }
+
+ @Override
+ public void writeDocument(MFProxy proxy, File outFile) throws IOException {
+
+ }
+
+ @Override
+ public void close() throws IOException {
+ bos.reset();
+ }
+}
diff --git a/src/ooxml/java/org/apache/poi/xslf/util/DummyGraphics2d.java b/src/ooxml/java/org/apache/poi/xslf/util/DummyGraphics2d.java
new file mode 100644
index 0000000000..281f4129d5
--- /dev/null
+++ b/src/ooxml/java/org/apache/poi/xslf/util/DummyGraphics2d.java
@@ -0,0 +1,1029 @@
+/* ====================================================================
+ 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.util;
+
+import java.awt.AlphaComposite;
+import java.awt.BasicStroke;
+import java.awt.Color;
+import java.awt.Composite;
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.GraphicsConfiguration;
+import java.awt.Image;
+import java.awt.Paint;
+import java.awt.Polygon;
+import java.awt.Rectangle;
+import java.awt.RenderingHints;
+import java.awt.Shape;
+import java.awt.Stroke;
+import java.awt.font.FontRenderContext;
+import java.awt.font.GlyphVector;
+import java.awt.font.TextAttribute;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Path2D;
+import java.awt.geom.PathIterator;
+import java.awt.image.BufferedImage;
+import java.awt.image.BufferedImageOp;
+import java.awt.image.ImageObserver;
+import java.awt.image.RenderedImage;
+import java.awt.image.renderable.RenderableImage;
+import java.io.PrintStream;
+import java.text.AttributedCharacterIterator;
+import java.text.AttributedCharacterIterator.Attribute;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.Locale;
+import java.util.Map;
+
+import org.apache.poi.util.Internal;
+
+public class DummyGraphics2d extends Graphics2D {
+ private BufferedImage bufimg;
+ private final Graphics2D g2D;
+ private final PrintStream log;
+
+ public DummyGraphics2d() {
+ this(System.out);
+ }
+
+ public DummyGraphics2d(PrintStream log) {
+ bufimg = new BufferedImage(1000, 1000, 2);
+ g2D = (Graphics2D)bufimg.getGraphics();
+ this.log = log;
+ }
+
+ public DummyGraphics2d(PrintStream log, Graphics2D g2D) {
+ this.g2D = g2D;
+ this.log = log;
+ }
+
+ public void addRenderingHints(Map<?,?> hints) {
+ String l =
+ "addRenderingHinds(Map):" +
+ "\n hints = " + hints;
+ log.println( l );
+ g2D.addRenderingHints( hints );
+ }
+
+ public void clip(Shape s) {
+ String l =
+ "clip(Shape):" +
+ "\n s = " + s;
+ log.println( l );
+ g2D.clip( s );
+ }
+
+ private void pathToString(StringBuilder sb, Path2D p) {
+ sb.append("Path2D p = new Path2D.Double("+p.getWindingRule()+");\n");
+ double[] coords = new double[6];
+
+ for (PathIterator pi = p.getPathIterator(null); !pi.isDone(); pi.next()) {
+ // The type will be SEG_LINETO, SEG_MOVETO, or SEG_CLOSE
+ // Because the Area is composed of straight lines
+ switch (pi.currentSegment(coords)) {
+ case PathIterator.SEG_MOVETO:
+ sb.append("p.moveTo("+coords[0]+","+coords[1]+");\n");
+ break;
+ case PathIterator.SEG_LINETO:
+ sb.append("p.lineTo("+coords[0]+","+coords[1]+");\n");
+ break;
+ case PathIterator.SEG_QUADTO:
+ sb.append("p.quadTo("+coords[0]+","+coords[1]+","+coords[2]+","+coords[3]+");\n");
+ break;
+ case PathIterator.SEG_CUBICTO:
+ sb.append("p.curveTo("+coords[0]+","+coords[1]+","+coords[2]+","+coords[3]+","+coords[4]+","+coords[5]+");\n");
+ break;
+ case PathIterator.SEG_CLOSE:
+ sb.append("p.closePath();\n");
+ break;
+ }
+ }
+ }
+
+ public void draw(Shape s) {
+ if (s instanceof Path2D) {
+ StringBuilder sb = new StringBuilder();
+ pathToString(sb, (Path2D)s);
+ sb.append("g.draw(p);");
+ log.println( sb.toString() );
+ } else {
+ log.println( "g.draw("+ s + ")" );
+ }
+ g2D.draw( s );
+ }
+
+ public void drawGlyphVector(GlyphVector g, float x, float y) {
+ String l =
+ "drawGlyphVector(GlyphVector, float, float):" +
+ "\n g = " + g +
+ "\n x = " + x +
+ "\n y = " + y;
+ log.println( l );
+ g2D.drawGlyphVector( g, x, y );
+ }
+
+ public void drawImage(BufferedImage img, BufferedImageOp op, int x, int y) {
+ String l =
+ "drawImage(BufferedImage, BufferedImageOp, x, y):" +
+ "\n img = " + img +
+ "\n op = " + op +
+ "\n x = " + x +
+ "\n y = " + y;
+ log.println( l );
+ g2D.drawImage( img, op, x, y );
+ }
+
+ public boolean drawImage(Image img, AffineTransform xform, ImageObserver obs) {
+ String l =
+ "drawImage(Image,AfflineTransform,ImageObserver):" +
+ "\n img = " + img +
+ "\n xform = " + xform +
+ "\n obs = " + obs;
+ log.println( l );
+ return g2D.drawImage( img, xform, obs );
+ }
+
+ public void drawRenderableImage(RenderableImage img, AffineTransform xform) {
+ String l =
+ "drawRenderableImage(RenderableImage, AfflineTransform):" +
+ "\n img = " + img +
+ "\n xform = " + xform;
+ log.println( l );
+ g2D.drawRenderableImage( img, xform );
+ }
+
+ public void drawRenderedImage(RenderedImage img, AffineTransform xform) {
+ String l =
+ "drawRenderedImage(RenderedImage, AffineTransform):" +
+ "\n img = " + img +
+ "\n xform = " + xform;
+ log.println( l );
+ g2D.drawRenderedImage( img, xform );
+ }
+
+ public void drawString(String s, float x, float y) {
+ String l =
+ "drawString(s,x,y):" +
+ "\n s = " + s +
+ "\n x = " + x +
+ "\n y = " + y;
+ log.println( l );
+ g2D.drawString( s, x, y );
+ }
+
+ public void fill(Shape s) {
+ if (s instanceof Path2D) {
+ StringBuilder sb = new StringBuilder();
+ pathToString(sb, (Path2D)s);
+ sb.append("g.fill(p);");
+ log.println( sb.toString() );
+ } else {
+ log.println( "g.fill("+ s + ")" );
+ }
+ g2D.fill( s );
+ }
+
+ public Color getBackground() {
+ log.println( "getBackground():" );
+ return g2D.getBackground();
+ }
+
+ public Composite getComposite() {
+ log.println( "getComposite():" );
+ return g2D.getComposite();
+ }
+
+ public GraphicsConfiguration getDeviceConfiguration() {
+ log.println( "getDeviceConfiguration():" );
+ return g2D.getDeviceConfiguration();
+ }
+
+ public FontRenderContext getFontRenderContext() {
+ log.println( "getFontRenderContext():" );
+ return g2D.getFontRenderContext();
+ }
+
+ public Paint getPaint() {
+ log.println( "getPaint():" );
+ return g2D.getPaint();
+ }
+
+ public Object getRenderingHint(RenderingHints.Key hintKey) {
+ log.println( "getRenderingHint(\""+hintKey+"\")" );
+ return g2D.getRenderingHint( hintKey );
+ }
+
+ public RenderingHints getRenderingHints() {
+ log.println( "getRenderingHints():" );
+ return g2D.getRenderingHints();
+ }
+
+ public Stroke getStroke() {
+ log.println( "getStroke():" );
+ return g2D.getStroke();
+ }
+
+ public AffineTransform getTransform() {
+ log.println( "getTransform():" );
+ return g2D.getTransform();
+ }
+
+ public boolean hit(Rectangle rect, Shape s, boolean onStroke) {
+ String l =
+ "hit(Rectangle, Shape, onStroke):" +
+ "\n rect = " + rect +
+ "\n s = " + s +
+ "\n onStroke = " + onStroke;
+ log.println( l );
+ return g2D.hit( rect, s, onStroke );
+ }
+
+ public void rotate(double theta) {
+ String l =
+ "rotate(theta):" +
+ "\n theta = " + theta;
+ log.println( l );
+ g2D.rotate( theta );
+ }
+
+ public void rotate(double theta, double x, double y) {
+ String l =
+ "rotate(double,double,double):" +
+ "\n theta = " + theta +
+ "\n x = " + x +
+ "\n y = " + y;
+ log.println( l );
+ g2D.rotate( theta, x, y );
+ }
+
+ public void scale(double sx, double sy) {
+ log.println( "g.scale("+sx+","+sy+");" );
+ g2D.scale( sx, sy );
+ }
+
+ public void setBackground(Color color) {
+ log.println(String.format(Locale.ROOT, "setBackground(new Color(0x%08X))", color.getRGB()));
+ g2D.setBackground( color );
+ }
+
+ private static final String[] COMPOSITE_RULES = {
+ "CLEAR", "SRC", "SRC_OVER", "DST_OVER", "SRC_IN", "DST_IN", "SRC_OUT", "DST_OUT", "DST", "SRC_ATOP", "DST_ATOP", "XOR"
+ };
+
+ public void setComposite(Composite comp) {
+ String l = "g.setComposite(";
+ if (comp instanceof AlphaComposite) {
+ AlphaComposite ac = (AlphaComposite)comp;
+ l += "AlphaComposite.getInstance(AlphaComposite."
+ + COMPOSITE_RULES[Math.max(0,Math.min(COMPOSITE_RULES.length-1,ac.getRule()))]
+ + ", " + ac.getAlpha() + "f));";
+ } else {
+ l += comp.toString() + ");";
+ }
+ log.println( l );
+ g2D.setComposite( comp );
+ }
+
+ public void setPaint( Paint paint ) {
+ String l = "g.setPaint(";
+ if (paint instanceof Color) {
+ l += String.format(Locale.ROOT, "new Color(0x%08X));", ((Color)paint).getRGB());
+ } else {
+ l += paint.toString() + ");";
+ }
+ log.println( l );
+ g2D.setPaint( paint );
+ }
+
+ public void setRenderingHint(RenderingHints.Key hintKey, Object hintValue) {
+ log.println( "g.setRenderingHint("+mapHint(hintKey)+", " + mapHint(hintValue) + ");" );
+ g2D.setRenderingHint( hintKey, hintValue );
+ }
+
+
+ private static String mapHint(Object hint) {
+ if (hint == null) {
+ return "null";
+ }
+ if (hint instanceof AffineTransform) {
+ return mapTransform((AffineTransform) hint);
+ }
+ for (int i=0; i<HINTS.length; i+=2) {
+ if (hint == HINTS[i]) {
+ return (String)HINTS[i+1];
+ }
+ }
+ return "\"" + hint.toString() + "\"";
+ }
+
+
+ public void setRenderingHints(Map<?,?> hints) {
+ String l =
+ "setRenderingHints(Map):" +
+ "\n hints = " + hints;
+ log.println( l );
+ g2D.setRenderingHints( hints );
+ }
+
+ public void setStroke(Stroke s) {
+ String l;
+ if (s instanceof BasicStroke) {
+ BasicStroke bs = (BasicStroke)s;
+ String cap = new String[]{"BUTT","ROUND","SQUARE"}[bs.getEndCap()];
+ String join = new String[]{"MITER","ROUND","BEVEL"}[bs.getLineJoin()];
+ l = "g.setStroke(new BasicStroke(" + bs.getLineWidth() + "f, BasicStroke.CAP_" + cap + ", BasicStroke.JOIN_" + join + ", " +
+ bs.getMiterLimit() + "f, " + Arrays.toString(bs.getDashArray()) + ", " + bs.getDashPhase() + "f));";
+ } else {
+ l = "g.setStroke(" + s + ");";
+ }
+ log.println( l );
+ g2D.setStroke( s );
+ }
+
+ private static String mapTransform(AffineTransform tx) {
+ return tx.isIdentity() ? "new AffineTransform()"
+ : "new AffineTransform("+tx.getScaleX()+"f,"+tx.getShearY()+"f,"+tx.getShearX()+"f,"+tx.getScaleY()+"f,"+tx.getTranslateX()+"f,"+tx.getTranslateY()+"f)";
+ }
+
+ public void setTransform(AffineTransform Tx) {
+ log.println( "g.setTransform("+mapTransform(Tx)+");" );
+ g2D.setTransform( Tx );
+ }
+
+ public void shear(double shx, double shy) {
+ String l =
+ "shear(shx, dhy):" +
+ "\n shx = " + shx +
+ "\n shy = " + shy;
+ log.println( l );
+ g2D.shear( shx, shy );
+ }
+
+ public void transform(AffineTransform Tx) {
+ String l =
+ "transform(AffineTransform):" +
+ "\n Tx = " + Tx;
+ log.println( l );
+ g2D.transform( Tx );
+ }
+
+ public void translate(double tx, double ty) {
+ String l =
+ "translate(double, double):" +
+ "\n tx = " + tx +
+ "\n ty = " + ty;
+ log.println( l );
+ g2D.translate( tx, ty );
+ }
+
+ public void clearRect(int x, int y, int width, int height) {
+ String l =
+ "clearRect(int,int,int,int):" +
+ "\n x = " + x +
+ "\n y = " + y +
+ "\n width = " + width +
+ "\n height = " + height;
+ log.println( l );
+ g2D.clearRect( x, y, width, height );
+ }
+
+ public void clipRect(int x, int y, int width, int height) {
+ String l =
+ "clipRect(int, int, int, int):" +
+ "\n x = " + x +
+ "\n y = " + y +
+ "\n width = " + width +
+ "height = " + height;
+ log.println( l );
+ g2D.clipRect( x, y, width, height );
+ }
+
+ public void copyArea(int x, int y, int width, int height, int dx, int dy) {
+ String l =
+ "copyArea(int,int,int,int):" +
+ "\n x = " + x +
+ "\n y = " + y +
+ "\n width = " + width +
+ "\n height = " + height;
+ log.println( l );
+ g2D.copyArea( x, y, width, height, dx, dy );
+ }
+
+ public Graphics create() {
+ log.println( "create():" );
+ return g2D.create();
+ }
+
+ public Graphics create(int x, int y, int width, int height) {
+ String l =
+ "create(int,int,int,int):" +
+ "\n x = " + x +
+ "\n y = " + y +
+ "\n width = " + width +
+ "\n height = " + height;
+ log.println( l );
+ return g2D.create( x, y, width, height );
+ }
+
+ public void dispose() {
+ log.println( "dispose():" );
+ g2D.dispose();
+ }
+
+ public void draw3DRect(int x, int y, int width, int height, boolean raised) {
+ String l =
+ "draw3DRect(int,int,int,int,boolean):" +
+ "\n x = " + x +
+ "\n y = " + y +
+ "\n width = " + width +
+ "\n height = " + height +
+ "\n raised = " + raised;
+ log.println( l );
+ g2D.draw3DRect( x, y, width, height, raised );
+ }
+
+ public void drawArc(int x, int y, int width, int height, int startAngle, int arcAngle) {
+ String l =
+ "drawArc(int,int,int,int,int,int):" +
+ "\n x = " + x +
+ "\n y = " + y +
+ "\n width = " + width +
+ "\n height = " + height +
+ "\n startAngle = " + startAngle +
+ "\n arcAngle = " + arcAngle;
+ log.println( l );
+ g2D.drawArc( x, y, width, height, startAngle, arcAngle );
+ }
+
+ public void drawBytes(byte[] data, int offset, int length, int x, int y) {
+ String l =
+ "drawBytes(byte[],int,int,int,int):" +
+ "\n data = " + Arrays.toString(data) +
+ "\n offset = " + offset +
+ "\n length = " + length +
+ "\n x = " + x +
+ "\n y = " + y;
+ log.println( l );
+ g2D.drawBytes( data, offset, length, x, y );
+ }
+
+ public void drawChars(char[] data, int offset, int length, int x, int y) {
+ String l =
+ "drawChars(data,int,int,int,int):" +
+ "\n data = " + Arrays.toString(data) +
+ "\n offset = " + offset +
+ "\n length = " + length +
+ "\n x = " + x +
+ "\n y = " + y;
+ log.println( l );
+ g2D.drawChars( data, offset, length, x, y );
+ }
+
+ public boolean drawImage(Image img, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2, int sy2, ImageObserver observer) {
+ String l =
+ "drawImage(Image,int,int,int,int,int,int,int,int,ImageObserver):" +
+ "\n img = " + img +
+ "\n dx1 = " + dx1 +
+ "\n dy1 = " + dy1 +
+ "\n dx2 = " + dx2 +
+ "\n dy2 = " + dy2 +
+ "\n sx1 = " + sx1 +
+ "\n sy1 = " + sy1 +
+ "\n sx2 = " + sx2 +
+ "\n sy2 = " + sy2 +
+ "\n observer = " + observer;
+ log.println( l );
+ return g2D.drawImage( img, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, observer );
+ }
+
+ public boolean drawImage(Image img, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2, int sy2, Color bgcolor, ImageObserver observer) {
+ String l =
+ "drawImage(Image,int,int,int,int,int,int,int,int,Color,ImageObserver):" +
+ "\n img = " + img +
+ "\n dx1 = " + dx1 +
+ "\n dy1 = " + dy1 +
+ "\n dx2 = " + dx2 +
+ "\n dy2 = " + dy2 +
+ "\n sx1 = " + sx1 +
+ "\n sy1 = " + sy1 +
+ "\n sx2 = " + sx2 +
+ "\n sy2 = " + sy2 +
+ "\n bgcolor = " + bgcolor +
+ "\n observer = " + observer;
+ log.println( l );
+ return g2D.drawImage( img, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, bgcolor, observer );
+ }
+
+ public boolean drawImage(Image img, int x, int y, Color bgcolor, ImageObserver observer) {
+ String l =
+ "drawImage(Image,int,int,Color,ImageObserver):" +
+ "\n img = " + img +
+ "\n x = " + x +
+ "\n y = " + y +
+ "\n bgcolor = " + bgcolor +
+ "\n observer = " + observer;
+ log.println( l );
+ return g2D.drawImage( img, x, y, bgcolor, observer );
+ }
+
+ public boolean drawImage(Image img, int x, int y, ImageObserver observer) {
+ String l =
+ "drawImage(Image,int,int,observer):" +
+ "\n img = " + img +
+ "\n x = " + x +
+ "\n y = " + y +
+ "\n observer = " + observer;
+ log.println( l );
+ return g2D.drawImage( img, x, y, observer );
+ }
+
+ public boolean drawImage(Image img, int x, int y, int width, int height, Color bgcolor, ImageObserver observer) {
+ String l =
+ "drawImage(Image,int,int,int,int,Color,ImageObserver):" +
+ "\n img = " + img +
+ "\n x = " + x +
+ "\n y = " + y +
+ "\n width = " + width +
+ "\n height = " + height +
+ "\n bgcolor = " + bgcolor +
+ "\n observer = " + observer;
+ log.println( l );
+ return g2D.drawImage( img, x, y, width, height, bgcolor, observer );
+ }
+
+ public boolean drawImage(Image img, int x, int y, int width, int height, ImageObserver observer) {
+ String l =
+ "drawImage(Image,int,int,width,height,observer):" +
+ "\n img = " + img +
+ "\n x = " + x +
+ "\n y = " + y +
+ "\n width = " + width +
+ "\n height = " + height +
+ "\n observer = " + observer;
+ log.println( l );
+ return g2D.drawImage( img, x, y, width, height, observer );
+ }
+
+ public void drawLine(int x1, int y1, int x2, int y2) {
+ String l =
+ "drawLine(int,int,int,int):" +
+ "\n x1 = " + x1 +
+ "\n y1 = " + y1 +
+ "\n x2 = " + x2 +
+ "\n y2 = " + y2;
+ log.println( l );
+ g2D.drawLine( x1, y1, x2, y2 );
+ }
+
+ public void drawOval(int x, int y, int width, int height) {
+ String l =
+ "drawOval(int,int,int,int):" +
+ "\n x = " + x +
+ "\n y = " + y +
+ "\n width = " + width +
+ "\n height = " + height;
+ log.println( l );
+ g2D.drawOval( x, y, width, height );
+ }
+
+ public void drawPolygon(Polygon p) {
+ String l =
+ "drawPolygon(Polygon):" +
+ "\n p = " + p;
+ log.println( l );
+ g2D.drawPolygon( p );
+ }
+
+ public void drawPolygon(int[] xPoints, int[] yPoints, int nPoints) {
+ String l =
+ "drawPolygon(int[],int[],int):" +
+ "\n xPoints = " + Arrays.toString(xPoints) +
+ "\n yPoints = " + Arrays.toString(yPoints) +
+ "\n nPoints = " + nPoints;
+ log.println( l );
+ g2D.drawPolygon( xPoints, yPoints, nPoints );
+ }
+
+ public void drawPolyline(int[] xPoints, int[] yPoints, int nPoints) {
+ String l =
+ "drawPolyline(int[],int[],int):" +
+ "\n xPoints = " + Arrays.toString(xPoints) +
+ "\n yPoints = " + Arrays.toString(yPoints) +
+ "\n nPoints = " + nPoints;
+ log.println( l );
+ g2D.drawPolyline( xPoints, yPoints, nPoints );
+ }
+
+ public void drawRect(int x, int y, int width, int height) {
+ String l =
+ "drawRect(int,int,int,int):" +
+ "\n x = " + x +
+ "\n y = " + y +
+ "\n width = " + width +
+ "\n height = " + height;
+ log.println( l );
+ g2D.drawRect( x, y, width, height );
+ }
+
+ public void drawRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight) {
+ String l =
+ "drawRoundRect(int,int,int,int,int,int):" +
+ "\n x = " + x +
+ "\n y = " + y +
+ "\n width = " + width +
+ "\n height = " + height +
+ "\n arcWidth = " + arcWidth +
+ "\n arcHeight = " + arcHeight;
+ log.println( l );
+ g2D.drawRoundRect( x, y, width, height, arcWidth, arcHeight );
+ }
+
+ private static String mapAttribute(Object attr) {
+ if (attr == null) {
+ return "null";
+ }
+ if (attr instanceof Font) {
+ Font f = (Font)attr;
+ final String[] STYLE = { "Font.PLAIN", "Font.BOLD", "Font.ITALIC", "Font.BOLD | Font.ITALIC" };
+ return "new Font(\"" + f.getFamily(Locale.ROOT) + "\"," + STYLE[f.getStyle()] + "," + f.getSize() + ")";
+ }
+ if (attr instanceof Color) {
+ return String.format(Locale.ROOT, "new Color(0x%08X)", ((Color)attr).getRGB());
+ }
+ for (int i=0; i<ATTRS.length; i+=2) {
+ if (attr == ATTRS[i]) {
+ return (String)ATTRS[i+1];
+ }
+ }
+ return "\""+attr.toString()+"\"";
+ }
+
+ public void drawString(AttributedCharacterIterator iterator, float x, float y) {
+ final int startIdx = iterator.getIndex();
+
+ final Map<Attribute, Map<Integer,Object>> attMap = new HashMap<>();
+ StringBuilder sb = new StringBuilder();
+ for (char ch = iterator.current(); ch != AttributedCharacterIterator.DONE; ch = iterator.next()) {
+ sb.append(ch);
+ iterator.getAttributes().forEach((k,v) ->
+ attMap.computeIfAbsent(k, (k2) -> new LinkedHashMap<>()).put(iterator.getIndex(), v)
+ );
+ }
+
+ String l = "AttributedString as = new AttributedString(\""+sb+"\");\n";
+ sb.setLength(0);
+ sb.append(l);
+
+ for (Map.Entry<Attribute, Map<Integer,Object>> me : attMap.entrySet()) {
+ int startPos = -2, lastPos = -2;
+ Object lastObj = null;
+ for (Map.Entry<Integer,Object> mo : me.getValue().entrySet()) {
+ int pos = mo.getKey();
+ Object obj = mo.getValue();
+ if (lastPos < pos-1 || obj != lastObj) {
+ if (startPos >= 0) {
+ Attribute at = me.getKey();
+ sb.append("as.addAttribute("+mapAttribute(me.getKey())+","+mapAttribute(lastObj)+","+startPos+","+(lastPos+1)+");\n");
+ }
+ startPos = pos;
+ }
+ lastPos = pos;
+ lastObj = obj;
+ }
+ if (lastObj != null) {
+ sb.append("as.addAttribute("+mapAttribute(me.getKey())+","+mapAttribute(lastObj)+","+startPos+","+(lastPos+1)+");\n");
+ }
+ }
+
+ sb.append("g.drawString(as.getIterator(),"+x+"f,"+y+"f);");
+ log.println( sb.toString() );
+
+ iterator.setIndex(startIdx);
+ g2D.drawString( iterator, x, y );
+ }
+
+
+ public void drawString(AttributedCharacterIterator iterator, int x, int y) {
+ drawString(iterator, (float)x, (float)y);
+ }
+
+ public void drawString(String str, int x, int y) {
+ String l =
+ "drawString(str,int,int):" +
+ "\n str = " + str +
+ "\n x = " + x +
+ "\n y = " + y;
+ log.println( l );
+ g2D.drawString( str, x, y );
+ }
+
+ public void fill3DRect(int x, int y, int width, int height, boolean raised) {
+ String l =
+ "fill3DRect(int,int,int,int,boolean):" +
+ "\n x = " + x +
+ "\n y = " + y +
+ "\n width = " + width +
+ "\n height = " + height +
+ "\n raised = " + raised;
+ log.println( l );
+ g2D.fill3DRect( x, y, width, height, raised );
+ }
+
+ public void fillArc(int x, int y, int width, int height, int startAngle, int arcAngle) {
+ String l =
+ "fillArc(int,int,int,int,int,int):" +
+ "\n x = " + x +
+ "\n y = " + y +
+ "\n width = " + width +
+ "\n height = " + height +
+ "\n startAngle = " + startAngle +
+ "\n arcAngle = " + arcAngle;
+ log.println( l );
+ g2D.fillArc( x, y, width, height, startAngle, arcAngle );
+ }
+
+ public void fillOval(int x, int y, int width, int height) {
+ String l =
+ "fillOval(int,int,int,int):" +
+ "\n x = " + x +
+ "\n y = " + y +
+ "\n width = " + width +
+ "\n height = " + height;
+ log.println( l );
+ g2D.fillOval( x, y, width, height );
+ }
+
+ public void fillPolygon(Polygon p) {
+ String l =
+ "fillPolygon(Polygon):" +
+ "\n p = " + p;
+ log.println( l );
+ g2D.fillPolygon( p );
+ }
+
+ public void fillPolygon(int[] xPoints, int[] yPoints, int nPoints) {
+ String l =
+ "fillPolygon(int[],int[],int):" +
+ "\n xPoints = " + Arrays.toString(xPoints) +
+ "\n yPoints = " + Arrays.toString(yPoints) +
+ "\n nPoints = " + nPoints;
+ log.println( l );
+ g2D.fillPolygon( xPoints, yPoints, nPoints );
+ }
+
+ public void fillRect(int x, int y, int width, int height) {
+ log.println( "g.fillRect(" + x + "," + y + "," + width + "," + height + ");" );
+ g2D.fillRect( x, y, width, height );
+ }
+
+ public void fillRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight) {
+ log.println( "fillRoundRect(" + x + "," + y + "," + width + "," + height + "," + arcWidth + "," + arcHeight + ")" );
+ g2D.fillRoundRect( x, y, width, height, arcWidth, arcHeight );
+ }
+
+ // FIXME: should be protected
+ // FindBugs, category MALICIOUS_CODE, FI_PUBLIC_SHOULD_BE_PROTECTED
+ // A class's finalize() method should have protected access, not public
+ @Internal
+ @Override
+ public final void finalize() {
+ log.println( "finalize():" );
+ g2D.dispose();
+ dispose();
+ }
+
+ public Shape getClip() {
+ log.println( "getClip():" );
+ return g2D.getClip();
+ }
+
+ public Rectangle getClipBounds() {
+ log.println( "getClipBounds():" );
+ return g2D.getClipBounds();
+ }
+
+ public Rectangle getClipBounds(Rectangle r) {
+ String l =
+ "getClipBounds(Rectangle):" +
+ "\n r = " + r;
+ log.println( l );
+ return g2D.getClipBounds( r );
+ }
+
+ public Color getColor() {
+ log.println( "getColor():" );
+ return g2D.getColor();
+ }
+
+ public Font getFont() {
+ log.println( "getFont():" );
+ return g2D.getFont();
+ }
+
+ public FontMetrics getFontMetrics() {
+ log.println( "getFontMetrics():" );
+ return g2D.getFontMetrics();
+ }
+
+ public FontMetrics getFontMetrics(Font f) {
+ log.println( "getFontMetrics():" );
+ return g2D.getFontMetrics( f );
+ }
+
+ public boolean hitClip(int x, int y, int width, int height) {
+ String l =
+ "hitClip(int,int,int,int):" +
+ "\n x = " + x +
+ "\n y = " + y +
+ "\n width = " + width +
+ "\n height = " + height;
+ log.println( l );
+ return g2D.hitClip( x, y, width, height );
+ }
+
+ public void setClip(Shape clip) {
+ String l =
+ "setClip(Shape):" +
+ "\n clip = " + clip;
+ log.println( l );
+ g2D.setClip( clip );
+ }
+
+ public void setClip(int x, int y, int width, int height) {
+ String l =
+ "setClip(int,int,int,int):" +
+ "\n x = " + x +
+ "\n y = " + y +
+ "\n width = " + width +
+ "\n height = " + height;
+ log.println( l );
+ g2D.setClip( x, y, width, height );
+ }
+
+ public void setColor(Color c) {
+ log.println( String.format(Locale.ROOT, "g.setColor(new Color(0x%08X));", c.getRGB()));
+ g2D.setColor( c );
+ }
+
+ public void setFont(Font font) {
+ String l =
+ "setFont(Font):" +
+ "\n font = " + font;
+ log.println( l );
+ g2D.setFont( font );
+ }
+
+ public void setPaintMode() {
+ log.println( "setPaintMode():" );
+ g2D.setPaintMode();
+ }
+
+ public void setXORMode(Color c1) {
+ String l =
+ "setXORMode(Color):" +
+ "\n c1 = " + c1;
+ log.println( l );
+ g2D.setXORMode( c1 );
+ }
+
+ public String toString() {
+ log.println( "toString():" );
+ return g2D.toString();
+ }
+
+ public void translate(int x, int y) {
+ String l =
+ "translate(int,int):" +
+ "\n x = " + x +
+ "\n y = " + y;
+ log.println( l );
+ g2D.translate( x, y );
+ }
+
+
+ private static final Object[] HINTS = {
+ RenderingHints.KEY_ANTIALIASING, "RenderingHints.KEY_ANTIALIASING",
+ RenderingHints.VALUE_ANTIALIAS_ON, "RenderingHints.VALUE_ANTIALIAS_ON",
+ RenderingHints.VALUE_ANTIALIAS_OFF, "RenderingHints.VALUE_ANTIALIAS_OFF",
+ RenderingHints.VALUE_ANTIALIAS_DEFAULT, "RenderingHints.VALUE_ANTIALIAS_DEFAULT",
+ RenderingHints.KEY_RENDERING, "RenderingHints.KEY_RENDERING",
+ RenderingHints.VALUE_RENDER_SPEED, "RenderingHints.VALUE_RENDER_SPEED",
+ RenderingHints.VALUE_RENDER_QUALITY, "RenderingHints.VALUE_RENDER_QUALITY",
+ RenderingHints.VALUE_RENDER_DEFAULT, "RenderingHints.VALUE_RENDER_DEFAULT",
+ RenderingHints.KEY_DITHERING, "RenderingHints.KEY_DITHERING",
+ RenderingHints.VALUE_DITHER_DISABLE, "RenderingHints.VALUE_DITHER_DISABLE",
+ RenderingHints.VALUE_DITHER_ENABLE, "RenderingHints.VALUE_DITHER_ENABLE",
+ RenderingHints.VALUE_DITHER_DEFAULT, "RenderingHints.VALUE_DITHER_DEFAULT",
+ RenderingHints.KEY_TEXT_ANTIALIASING, "RenderingHints.KEY_TEXT_ANTIALIASING",
+ RenderingHints.VALUE_TEXT_ANTIALIAS_ON, "RenderingHints.VALUE_TEXT_ANTIALIAS_ON",
+ RenderingHints.VALUE_TEXT_ANTIALIAS_OFF, "RenderingHints.VALUE_TEXT_ANTIALIAS_OFF",
+ RenderingHints.VALUE_TEXT_ANTIALIAS_DEFAULT, "RenderingHints.VALUE_TEXT_ANTIALIAS_DEFAULT",
+ RenderingHints.VALUE_TEXT_ANTIALIAS_GASP, "RenderingHints.VALUE_TEXT_ANTIALIAS_GASP",
+ RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB, "RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB",
+ RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HBGR, "RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HBGR",
+ RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_VRGB, "RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_VRGB",
+ RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_VBGR, "RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_VBGR",
+ RenderingHints.KEY_TEXT_LCD_CONTRAST, "RenderingHints.KEY_TEXT_LCD_CONTRAST",
+ RenderingHints.KEY_FRACTIONALMETRICS, "RenderingHints.KEY_FRACTIONALMETRICS",
+ RenderingHints.VALUE_FRACTIONALMETRICS_OFF, "RenderingHints.VALUE_FRACTIONALMETRICS_OFF",
+ RenderingHints.VALUE_FRACTIONALMETRICS_ON, "RenderingHints.VALUE_FRACTIONALMETRICS_ON",
+ RenderingHints.VALUE_FRACTIONALMETRICS_DEFAULT, "RenderingHints.VALUE_FRACTIONALMETRICS_DEFAULT",
+ RenderingHints.KEY_INTERPOLATION, "RenderingHints.KEY_INTERPOLATION",
+ RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR, "RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR",
+ RenderingHints.VALUE_INTERPOLATION_BILINEAR, "RenderingHints.VALUE_INTERPOLATION_BILINEAR",
+ RenderingHints.VALUE_INTERPOLATION_BICUBIC, "RenderingHints.VALUE_INTERPOLATION_BICUBIC",
+ RenderingHints.KEY_ALPHA_INTERPOLATION, "RenderingHints.KEY_ALPHA_INTERPOLATION",
+ RenderingHints.VALUE_ALPHA_INTERPOLATION_SPEED, "RenderingHints.VALUE_ALPHA_INTERPOLATION_SPEED",
+ RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY, "RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY",
+ RenderingHints.VALUE_ALPHA_INTERPOLATION_DEFAULT, "RenderingHints.VALUE_ALPHA_INTERPOLATION_DEFAULT",
+ RenderingHints.KEY_COLOR_RENDERING, "RenderingHints.KEY_COLOR_RENDERING",
+ RenderingHints.VALUE_COLOR_RENDER_SPEED, "RenderingHints.VALUE_COLOR_RENDER_SPEED",
+ RenderingHints.VALUE_COLOR_RENDER_QUALITY, "RenderingHints.VALUE_COLOR_RENDER_QUALITY",
+ RenderingHints.VALUE_COLOR_RENDER_DEFAULT, "RenderingHints.VALUE_COLOR_RENDER_DEFAULT",
+ RenderingHints.KEY_STROKE_CONTROL, "RenderingHints.KEY_STROKE_CONTROL",
+ RenderingHints.VALUE_STROKE_DEFAULT, "RenderingHints.VALUE_STROKE_DEFAULT",
+ RenderingHints.VALUE_STROKE_NORMALIZE, "RenderingHints.VALUE_STROKE_NORMALIZE",
+ RenderingHints.VALUE_STROKE_PURE, "RenderingHints.VALUE_STROKE_PURE"
+ };
+
+ private static final Object[] ATTRS = {
+ TextAttribute.FAMILY, "TextAttribute.FAMILY",
+ TextAttribute.WEIGHT, "TextAttribute.WEIGHT",
+ TextAttribute.WEIGHT_EXTRA_LIGHT, "TextAttribute.WEIGHT_EXTRA_LIGHT",
+ TextAttribute.WEIGHT_LIGHT, "TextAttribute.WEIGHT_LIGHT",
+ TextAttribute.WEIGHT_DEMILIGHT, "TextAttribute.WEIGHT_DEMILIGHT",
+ TextAttribute.WEIGHT_REGULAR, "TextAttribute.WEIGHT_REGULAR",
+ TextAttribute.WEIGHT_SEMIBOLD, "TextAttribute.WEIGHT_SEMIBOLD",
+ TextAttribute.WEIGHT_MEDIUM, "TextAttribute.WEIGHT_MEDIUM",
+ TextAttribute.WEIGHT_DEMIBOLD, "TextAttribute.WEIGHT_DEMIBOLD",
+ TextAttribute.WEIGHT_BOLD, "TextAttribute.WEIGHT_BOLD",
+ TextAttribute.WEIGHT_HEAVY, "TextAttribute.WEIGHT_HEAVY",
+ TextAttribute.WEIGHT_EXTRABOLD, "TextAttribute.WEIGHT_EXTRABOLD",
+ TextAttribute.WEIGHT_ULTRABOLD, "TextAttribute.WEIGHT_ULTRABOLD",
+ TextAttribute.WIDTH, "TextAttribute.WIDTH",
+ TextAttribute.WIDTH_CONDENSED, "TextAttribute.WIDTH_CONDENSED",
+ TextAttribute.WIDTH_SEMI_CONDENSED, "TextAttribute.WIDTH_SEMI_CONDENSED",
+ TextAttribute.WIDTH_REGULAR, "TextAttribute.WIDTH_REGULAR",
+ TextAttribute.WIDTH_SEMI_EXTENDED, "TextAttribute.WIDTH_SEMI_EXTENDED",
+ TextAttribute.WIDTH_EXTENDED, "TextAttribute.WIDTH_EXTENDED",
+ TextAttribute.POSTURE, "TextAttribute.POSTURE",
+ TextAttribute.POSTURE_REGULAR, "TextAttribute.POSTURE_REGULAR",
+ TextAttribute.POSTURE_OBLIQUE, "TextAttribute.POSTURE_OBLIQUE",
+ TextAttribute.SIZE, "TextAttribute.SIZE",
+ TextAttribute.TRANSFORM, "TextAttribute.TRANSFORM",
+ TextAttribute.SUPERSCRIPT, "TextAttribute.SUPERSCRIPT",
+ TextAttribute.SUPERSCRIPT_SUPER, "TextAttribute.SUPERSCRIPT_SUPER",
+ TextAttribute.SUPERSCRIPT_SUB, "TextAttribute.SUPERSCRIPT_SUB",
+ TextAttribute.FONT, "TextAttribute.FONT",
+ TextAttribute.CHAR_REPLACEMENT, "TextAttribute.CHAR_REPLACEMENT",
+ TextAttribute.FOREGROUND, "TextAttribute.FOREGROUND",
+ TextAttribute.BACKGROUND, "TextAttribute.BACKGROUND",
+ TextAttribute.UNDERLINE, "TextAttribute.UNDERLINE",
+ TextAttribute.UNDERLINE_ON, "TextAttribute.UNDERLINE_ON",
+ TextAttribute.STRIKETHROUGH, "TextAttribute.STRIKETHROUGH",
+ TextAttribute.STRIKETHROUGH_ON, "TextAttribute.STRIKETHROUGH_ON",
+ TextAttribute.RUN_DIRECTION, "TextAttribute.RUN_DIRECTION",
+ TextAttribute.RUN_DIRECTION_LTR, "TextAttribute.RUN_DIRECTION_LTR",
+ TextAttribute.RUN_DIRECTION_RTL, "TextAttribute.RUN_DIRECTION_RTL",
+ TextAttribute.BIDI_EMBEDDING, "TextAttribute.BIDI_EMBEDDING",
+ TextAttribute.JUSTIFICATION, "TextAttribute.JUSTIFICATION",
+ TextAttribute.JUSTIFICATION_FULL, "TextAttribute.JUSTIFICATION_FULL",
+ TextAttribute.JUSTIFICATION_NONE, "TextAttribute.JUSTIFICATION_NONE",
+ TextAttribute.INPUT_METHOD_HIGHLIGHT, "TextAttribute.INPUT_METHOD_HIGHLIGHT",
+ TextAttribute.INPUT_METHOD_UNDERLINE, "TextAttribute.INPUT_METHOD_UNDERLINE",
+ TextAttribute.UNDERLINE_LOW_ONE_PIXEL, "TextAttribute.UNDERLINE_LOW_ONE_PIXEL",
+ TextAttribute.UNDERLINE_LOW_TWO_PIXEL, "TextAttribute.UNDERLINE_LOW_TWO_PIXEL",
+ TextAttribute.UNDERLINE_LOW_DOTTED, "TextAttribute.UNDERLINE_LOW_DOTTED",
+ TextAttribute.UNDERLINE_LOW_GRAY, "TextAttribute.UNDERLINE_LOW_GRAY",
+ TextAttribute.UNDERLINE_LOW_DASHED, "TextAttribute.UNDERLINE_LOW_DASHED",
+ TextAttribute.SWAP_COLORS, "TextAttribute.SWAP_COLORS",
+ TextAttribute.SWAP_COLORS_ON, "TextAttribute.SWAP_COLORS_ON",
+ TextAttribute.NUMERIC_SHAPING, "TextAttribute.NUMERIC_SHAPING",
+ TextAttribute.KERNING, "TextAttribute.KERNING",
+ TextAttribute.KERNING_ON, "TextAttribute.KERNING_ON",
+ TextAttribute.LIGATURES, "TextAttribute.LIGATURES",
+ TextAttribute.LIGATURES_ON, "TextAttribute.LIGATURES_ON",
+ TextAttribute.TRACKING, "TextAttribute.TRACKING",
+ TextAttribute.TRACKING_TIGHT, "TextAttribute.TRACKING_TIGHT",
+ TextAttribute.TRACKING_LOOSE, "TextAttribute.TRACKING_LOOSE"
+ };
+}
diff --git a/src/ooxml/java/org/apache/poi/xslf/util/PPTX2PNG.java b/src/ooxml/java/org/apache/poi/xslf/util/PPTX2PNG.java
index 609b3efcbb..33c5703f8b 100644
--- a/src/ooxml/java/org/apache/poi/xslf/util/PPTX2PNG.java
+++ b/src/ooxml/java/org/apache/poi/xslf/util/PPTX2PNG.java
@@ -63,7 +63,7 @@ public final class PPTX2PNG {
" -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,svg,pdf (,null for testing)\n" +
+ " -format <type> png,gif,jpg,svg,pdf (,log,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" +
@@ -239,7 +239,7 @@ public final class PPTX2PNG {
return false;
}
- if (format == null || !format.matches("^(png|gif|jpg|null|svg|pdf)$")) {
+ if (format == null || !format.matches("^(png|gif|jpg|null|svg|pdf|log)$")) {
usage("Invalid format given");
return false;
}
@@ -354,6 +354,8 @@ public final class PPTX2PNG {
return new SVGFormat(textAsShapes);
case "pdf":
return new PDFFormat(textAsShapes,fontDir,fontTtf);
+ case "log":
+ return new DummyFormat();
default:
return new BitmapFormat(format);
}
diff --git a/src/ooxml/testcases/org/apache/poi/xslf/TestXSLFBugs.java b/src/ooxml/testcases/org/apache/poi/xslf/TestXSLFBugs.java
index 19222c7006..adfa7ed46e 100644
--- a/src/ooxml/testcases/org/apache/poi/xslf/TestXSLFBugs.java
+++ b/src/ooxml/testcases/org/apache/poi/xslf/TestXSLFBugs.java
@@ -17,6 +17,8 @@
package org.apache.poi.xslf;
import static org.apache.poi.POITestCase.assertContains;
+import static org.apache.poi.sl.draw.DrawTextParagraph.HYPERLINK_HREF;
+import static org.apache.poi.sl.draw.DrawTextParagraph.HYPERLINK_LABEL;
import static org.apache.poi.xslf.XSLFTestDataSamples.openSampleDocument;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
@@ -25,6 +27,7 @@ import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import static org.junit.Assume.assumeFalse;
import java.awt.Color;
import java.awt.Dimension;
@@ -39,16 +42,23 @@ import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
+import java.text.AttributedCharacterIterator;
+import java.text.AttributedCharacterIterator.Attribute;
+import java.text.CharacterIterator;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
import java.util.List;
+import java.util.Map;
import java.util.Optional;
import java.util.function.Function;
import java.util.stream.Collectors;
+import java.util.stream.Stream;
import javax.imageio.ImageIO;
import org.apache.poi.POIDataSamples;
+import org.apache.poi.common.usermodel.HyperlinkType;
import org.apache.poi.ooxml.POIXMLDocumentPart;
import org.apache.poi.ooxml.POIXMLDocumentPart.RelationPart;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
@@ -57,6 +67,7 @@ import org.apache.poi.openxml4j.opc.PackagePartName;
import org.apache.poi.openxml4j.opc.PackagingURIHelper;
import org.apache.poi.sl.draw.DrawPaint;
import org.apache.poi.sl.extractor.SlideShowExtractor;
+import org.apache.poi.sl.usermodel.Hyperlink;
import org.apache.poi.sl.usermodel.PaintStyle;
import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint;
import org.apache.poi.sl.usermodel.PaintStyle.TexturePaint;
@@ -66,8 +77,13 @@ import org.apache.poi.sl.usermodel.PictureShape;
import org.apache.poi.sl.usermodel.Shape;
import org.apache.poi.sl.usermodel.ShapeType;
import org.apache.poi.sl.usermodel.Slide;
+import org.apache.poi.sl.usermodel.SlideShow;
+import org.apache.poi.sl.usermodel.SlideShowFactory;
+import org.apache.poi.sl.usermodel.TextRun;
+import org.apache.poi.sl.usermodel.TextShape;
import org.apache.poi.sl.usermodel.VerticalAlignment;
import org.apache.poi.util.IOUtils;
+import org.apache.poi.util.NullPrintStream;
import org.apache.poi.xslf.usermodel.XMLSlideShow;
import org.apache.poi.xslf.usermodel.XSLFAutoShape;
import org.apache.poi.xslf.usermodel.XSLFGroupShape;
@@ -87,6 +103,8 @@ import org.apache.poi.xslf.usermodel.XSLFTableRow;
import org.apache.poi.xslf.usermodel.XSLFTextBox;
import org.apache.poi.xslf.usermodel.XSLFTextParagraph;
import org.apache.poi.xslf.usermodel.XSLFTextRun;
+import org.apache.poi.xslf.util.DummyGraphics2d;
+import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;
import org.openxmlformats.schemas.drawingml.x2006.main.CTOuterShadowEffect;
@@ -95,6 +113,17 @@ import org.openxmlformats.schemas.presentationml.x2006.main.CTShape;
public class TestXSLFBugs {
private static final POIDataSamples slTests = POIDataSamples.getSlideShowInstance();
+ private static boolean xslfOnly;
+
+ @BeforeClass
+ public static void checkHslf() {
+ try {
+ Class.forName("org.apache.poi.hslf.usermodel.HSLFSlideShow");
+ } catch (Exception e) {
+ xslfOnly = true;
+ }
+ }
+
@Test
public void bug62929() throws Exception {
try(XMLSlideShow ss1 = openSampleDocument("missing-blip-fill.pptx")) {
@@ -247,9 +276,9 @@ public class TestXSLFBugs {
public void bug62587() throws IOException {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try (XMLSlideShow ppt = new XMLSlideShow()) {
- Slide slide = ppt.createSlide();
+ Slide<?,?> slide = ppt.createSlide();
XSLFPictureData pd = ppt.addPicture(slTests.getFile("wrench.emf"), PictureType.EMF);
- PictureShape ps = slide.createPicture(pd);
+ PictureShape<?,?> ps = slide.createPicture(pd);
ps.setAnchor(new Rectangle2D.Double(100,100,100,100));
ppt.write(bos);
}
@@ -584,9 +613,7 @@ public class TestXSLFBugs {
// Some dummy pictures
byte[][] pics = new byte[15][3];
for (int i=0; i<pics.length; i++) {
- for (int j=0; j<pics[i].length; j++) {
- pics[i][j] = (byte)i;
- }
+ Arrays.fill(pics[i], (byte) i);
}
// Add a few pictures
@@ -1011,4 +1038,53 @@ public class TestXSLFBugs {
assertEquals("Picture 5", ps.getShapeName());
}
}
+
+
+ @Test
+ public void bug57796() throws IOException {
+ assumeFalse(xslfOnly);
+
+ try (SlideShow<?,?> ppt = SlideShowFactory.create(slTests.getFile("WithLinks.ppt"))) {
+ Slide<?,?> slide = ppt.getSlides().get(0);
+ TextShape<?,?> shape = (TextShape<?,?>) slide.getShapes().get(1);
+ TextRun r = shape.getTextParagraphs().get(1).getTextRuns().get(0);
+ Hyperlink<?,?> hlRun = r.getHyperlink();
+ assertNotNull(hlRun);
+ assertEquals("http://jakarta.apache.org/poi/", hlRun.getAddress());
+ assertEquals("http://jakarta.apache.org/poi/", hlRun.getLabel());
+ assertEquals(HyperlinkType.URL, hlRun.getType());
+
+ final List<Object> strings = new ArrayList<>();
+
+ DummyGraphics2d dgfx = new DummyGraphics2d(new NullPrintStream()) {
+ @Override
+ public void drawString(AttributedCharacterIterator iterator, float x, float y) {
+ // For the test file, common sl draws textruns one by one and not mixed
+ // so we evaluate the whole iterator
+ Map<Attribute, Object> attributes = null;
+ StringBuilder sb = new StringBuilder();
+
+ for (char c = iterator.first();
+ c != CharacterIterator.DONE;
+ c = iterator.next()) {
+ sb.append(c);
+ attributes = iterator.getAttributes();
+ }
+
+ if ("Jakarta HSSF".equals(sb.toString())) {
+ // this is a test for a manually modified ppt, for real hyperlink label
+ // one would need to access the screen tip record
+ Attribute[] obj = { HYPERLINK_HREF, HYPERLINK_LABEL };
+ assertNotNull(attributes);
+ Stream.of(obj).map(attributes::get).forEach(strings::add);
+ }
+ }
+ };
+
+ ppt.getSlides().get(1).draw(dgfx);
+ assertEquals(2, strings.size());
+ assertEquals("http://jakarta.apache.org/poi/hssf/", strings.get(0));
+ assertEquals("Open Jakarta POI HSSF module test ", strings.get(1));
+ }
+ }
}