diff --git a/src/java/org/apache/poi/sl/draw/DrawPaint.java b/src/java/org/apache/poi/sl/draw/DrawPaint.java
index 25affcedf8..f674aa1317 100644
--- a/src/java/org/apache/poi/sl/draw/DrawPaint.java
+++ b/src/java/org/apache/poi/sl/draw/DrawPaint.java
@@ -17,6 +17,8 @@
package org.apache.poi.sl.draw;
+import static org.apache.poi.sl.draw.geom.ArcToCommand.convertOoxml2AwtAngle;
+
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.LinearGradientPaint;
@@ -443,6 +445,8 @@ public class DrawPaint {
Rectangle2D anchor = DrawShape.getAnchor(graphics, shape);
+ angle = convertOoxml2AwtAngle(-angle, anchor.getWidth(), anchor.getHeight());
+
AffineTransform at = AffineTransform.getRotateInstance(Math.toRadians(angle), anchor.getCenterX(), anchor.getCenterY());
double diagonal = Math.sqrt(Math.pow(anchor.getWidth(),2) + Math.pow(anchor.getHeight(),2));
diff --git a/src/java/org/apache/poi/sl/draw/PathGradientPaint.java b/src/java/org/apache/poi/sl/draw/PathGradientPaint.java
index 2281bbff83..a26abadd2e 100644
--- a/src/java/org/apache/poi/sl/draw/PathGradientPaint.java
+++ b/src/java/org/apache/poi/sl/draw/PathGradientPaint.java
@@ -17,11 +17,27 @@
package org.apache.poi.sl.draw;
-import java.awt.*;
+import java.awt.AlphaComposite;
+import java.awt.BasicStroke;
+import java.awt.Color;
+import java.awt.Graphics2D;
+import java.awt.LinearGradientPaint;
import java.awt.MultipleGradientPaint.ColorSpaceType;
import java.awt.MultipleGradientPaint.CycleMethod;
-import java.awt.geom.*;
-import java.awt.image.*;
+import java.awt.Paint;
+import java.awt.PaintContext;
+import java.awt.Rectangle;
+import java.awt.RenderingHints;
+import java.awt.Shape;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Area;
+import java.awt.geom.IllegalPathStateException;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+import java.awt.image.BufferedImage;
+import java.awt.image.ColorModel;
+import java.awt.image.Raster;
+import java.awt.image.WritableRaster;
import org.apache.poi.util.Internal;
@@ -174,14 +190,17 @@ class PathGradientPaint implements Paint {
int[] rgb = new int[cm.getNumComponents()];
for (int i = gradientSteps-1; i>=0; i--) {
- img2.getPixel(i, 0, rgb);
+ img2.getPixel(gradientSteps-i-1, 0, rgb);
Color c = new Color(rgb[0],rgb[1],rgb[2]);
if (rgb.length == 4) {
// it doesn't work to use just a color with transparency ...
- graphics.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC, rgb[3]/255.0f));
+ graphics.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC, rgb[3]/255.0f));
}
graphics.setStroke(new BasicStroke(i+1, capStyle, joinStyle));
graphics.setColor(c);
+ if (i == gradientSteps-1) {
+ graphics.fill(shape);
+ }
graphics.draw(shape);
}
diff --git a/src/java/org/apache/poi/sl/draw/geom/ArcToCommand.java b/src/java/org/apache/poi/sl/draw/geom/ArcToCommand.java
index 7d0feb366e..9ff57e6da9 100644
--- a/src/java/org/apache/poi/sl/draw/geom/ArcToCommand.java
+++ b/src/java/org/apache/poi/sl/draw/geom/ArcToCommand.java
@@ -26,6 +26,7 @@ import java.awt.geom.Path2D;
import java.awt.geom.Point2D;
import org.apache.poi.sl.draw.binding.CTPath2DArcTo;
+import org.apache.poi.util.Internal;
/**
* ArcTo command within a shape path in DrawingML:
@@ -89,15 +90,16 @@ public class ArcToCommand implements PathCommand {
* |270/-90 |90/-270 (5400000)
*
*
- * @param ooAngle the angle in OOXML units
- * @param width the half width of the bounding box
- * @param height the half height of the bounding box
+ * @param ooAngle the angle in OOXML units divided by 60000
+ * @param width the width of the bounding box
+ * @param height the height of the bounding box
*
* @return the angle in degrees
*
* @see unskew angle
**/
- private double convertOoxml2AwtAngle(double ooAngle, double width, double height) {
+ @Internal
+ public static double convertOoxml2AwtAngle(double ooAngle, double width, double height) {
double aspect = (height / width);
// reverse angle for awt
double awtAngle = -ooAngle;
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 4c7e27d558..5a2b8dbe7e 100644
--- a/src/ooxml/java/org/apache/poi/xslf/util/PPTX2PNG.java
+++ b/src/ooxml/java/org/apache/poi/xslf/util/PPTX2PNG.java
@@ -225,7 +225,7 @@ public class PPTX2PNG {
proxy.setSlideNo(slideNo);
if (!quiet) {
String title = proxy.getTitle();
- System.out.println("Rendering slide " + (slideNo + 1) + (title == null ? "" : ": " + title.trim()));
+ System.out.println("Rendering slide " + slideNo + (title == null ? "" : ": " + title.trim()));
}
GenericRecord gr = proxy.getRoot();
@@ -301,8 +301,6 @@ public class PPTX2PNG {
private interface MFProxy extends Closeable {
void parse(File file) throws IOException;
-// boolean isEmpty();
-// void dumpRecords(Writer writer) throws IOException;
// Iterable getEmbeddings();
Dimension2D getSize();
diff --git a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFFill.java b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFFill.java
index b87d2869be..3b505f703e 100644
--- a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFFill.java
+++ b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFFill.java
@@ -20,6 +20,8 @@ package org.apache.poi.hslf.usermodel;
import java.awt.Color;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
import org.apache.poi.ddf.AbstractEscherOptRecord;
@@ -229,6 +231,19 @@ public final class HSLFFill {
return new FillStyle() {
@Override
public PaintStyle getPaint() {
+ AbstractEscherOptRecord opt = shape.getEscherOptRecord();
+
+ EscherSimpleProperty hitProp = HSLFShape.getEscherProperty(opt, EscherPropertyTypes.FILL__NOFILLHITTEST);
+ int propVal = (hitProp == null) ? 0 : hitProp.getPropertyValue();
+
+ EscherSimpleProperty masterProp = HSLFShape.getEscherProperty(opt, EscherPropertyTypes.SHAPE__MASTER);
+
+ if (!FILL_USE_FILLED.isSet(propVal) && masterProp != null) {
+ int masterId = masterProp.getPropertyValue();
+ HSLFShape o = shape.getSheet().getMasterSheet().getShapes().stream().filter(s -> s.getShapeId() == masterId).findFirst().orElse(null);
+ return o != null ? o.getFillStyle().getPaint() : null;
+ }
+
final int fillType = getFillType();
// TODO: fix gradient types, this mismatches with the MS-ODRAW definition ...
// need to handle (not only) the type (radial,rectangular,linear),
@@ -265,9 +280,61 @@ public final class HSLFFill {
private GradientPaint getGradientPaint(final GradientType gradientType) {
AbstractEscherOptRecord opt = shape.getEscherOptRecord();
+
+ EscherSimpleProperty p = HSLFShape.getEscherProperty(opt, EscherPropertyTypes.FILL__NOFILLHITTEST);
+ int propVal = (p == null) ? 0 : p.getPropertyValue();
+
+ if (FILL_USE_FILLED.isSet(propVal) && !FILL_FILLED.isSet(propVal)) {
+ return null;
+ }
+
+
final EscherArrayProperty ep = HSLFShape.getEscherProperty(opt, EscherPropertyTypes.FILL__SHADECOLORS);
final int colorCnt = (ep == null) ? 0 : ep.getNumberOfElementsInArray();
+ final List colors = new ArrayList<>();
+ final List fractions = new ArrayList<>();
+
+ // TODO: handle palette colors and alpha(?) value
+ if (colorCnt == 0) {
+ colors.add(getBackgroundColor());
+ colors.add(getForegroundColor());
+ fractions.add(0f);
+ fractions.add(1f);
+ } else {
+ ep.forEach(data -> {
+ EscherColorRef ecr = new EscherColorRef(data, 0, 4);
+ colors.add(shape.getColor(ecr));
+ double pos = Units.fixedPointToDouble(LittleEndian.getInt(data, 4));
+ fractions.add((float)pos);
+ });
+ }
+
+ int focus = getFillFocus();
+ if (focus == 100 || focus == -100) {
+ Collections.reverse(colors);
+ } else if (focus != 0) {
+ if (focus < 0) {
+ focus = 100+focus;
+ }
+ // TODO: depending on fill focus, rotation with shape and other escher properties
+ // there are still a lot of cases where we get the gradients wrong
+ List reflectedColors = new ArrayList<>(colors.subList(1,colors.size()));
+ Collections.reverse(reflectedColors);
+ colors.addAll(0, reflectedColors);
+
+ final List fractRev = new ArrayList<>();
+ for (int i=fractions.size()-2; i >= 0; i--) {
+ float val = (float)(1 - fractions.get(i) * focus / 100.);
+ fractRev.add(val);
+ }
+ for (int i=0; i {
// a different color type
switch (sis) {
case FILL_COLOR: {
- return getFill().getForegroundColor();
+ return getColor(EscherPropertyTypes.FILL__FILLCOLOR, EscherPropertyTypes.FILL__FILLOPACITY);
}
case LINE_OR_FILL_COLOR: {
Color col = null;
if (this instanceof HSLFSimpleShape) {
- col = ((HSLFSimpleShape)this).getLineColor();
+ col = getColor(EscherPropertyTypes.LINESTYLE__COLOR, EscherPropertyTypes.LINESTYLE__OPACITY);
}
if (col == null) {
- col = getFill().getForegroundColor();
+ col = getColor(EscherPropertyTypes.FILL__FILLCOLOR, EscherPropertyTypes.FILL__FILLOPACITY);
}
return col;
}
case LINE_COLOR: {
if (this instanceof HSLFSimpleShape) {
- return ((HSLFSimpleShape)this).getLineColor();
+ return getColor(EscherPropertyTypes.LINESTYLE__COLOR, EscherPropertyTypes.LINESTYLE__OPACITY);
}
break;
}
@@ -536,7 +536,7 @@ public abstract class HSLFShape implements Shape {
break;
}
case FILL_BACKGROUND_COLOR: {
- return getFill().getBackgroundColor();
+ return getColor(EscherPropertyTypes.FILL__FILLBACKCOLOR, EscherPropertyTypes.FILL__FILLOPACITY);
}
case LINE_BACKGROUND_COLOR: {
if (this instanceof HSLFSimpleShape) {
@@ -545,9 +545,9 @@ public abstract class HSLFShape implements Shape {
break;
}
case FILL_OR_LINE_COLOR: {
- Color col = getFill().getForegroundColor();
+ Color col = getColor(EscherPropertyTypes.FILL__FILLCOLOR, EscherPropertyTypes.FILL__FILLOPACITY);
if (col == null && this instanceof HSLFSimpleShape) {
- col = ((HSLFSimpleShape)this).getLineColor();
+ col = getColor(EscherPropertyTypes.LINESTYLE__COLOR, EscherPropertyTypes.LINESTYLE__OPACITY);
}
return col;
}