#64088 - SlideShow rendering fixes

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1872984 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Andreas Beeker 2020-01-19 20:44:36 +00:00
parent 5927fd37f2
commit 0fb322bb92
22 changed files with 580 additions and 345 deletions

View File

@ -245,6 +245,9 @@ public class BitmapImageRenderer implements ImageRenderer {
double h_old = img.getHeight();
double w_new = dim.getWidth();
double h_new = dim.getHeight();
if (w_old == w_new && h_old == h_new) {
return img;
}
BufferedImage scaled = new BufferedImage((int)w_new, (int)h_new, BufferedImage.TYPE_INT_ARGB);
AffineTransform at = new AffineTransform();
at.scale(w_new/w_old, h_new/h_old);

View File

@ -22,7 +22,10 @@ import static org.apache.poi.sl.draw.geom.ArcToCommand.convertOoxml2AwtAngle;
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.Paint;
import java.awt.Point;
import java.awt.RadialGradientPaint;
import java.awt.Shape;
import java.awt.geom.AffineTransform;
@ -30,15 +33,24 @@ import java.awt.geom.Dimension2D;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferInt;
import java.awt.image.DirectColorModel;
import java.awt.image.Raster;
import java.awt.image.WritableRaster;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.TreeMap;
import java.util.function.BiFunction;
import java.util.stream.Stream;
import org.apache.poi.sl.usermodel.AbstractColorStyle;
import org.apache.poi.sl.usermodel.ColorStyle;
import org.apache.poi.sl.usermodel.Insets2D;
import org.apache.poi.sl.usermodel.PaintStyle;
import org.apache.poi.sl.usermodel.PaintStyle.FlipMode;
import org.apache.poi.sl.usermodel.PaintStyle.GradientPaint;
@ -214,6 +226,9 @@ public class DrawPaint {
}
private int scale(int value, PaintModifier lessModifier, PaintModifier moreModifier) {
if (value == -1) {
return -1;
}
int delta = (modifier == lessModifier ? 20000 : (modifier == moreModifier ? 40000 : 0));
return Math.min(100000, Math.max(0,value)+delta);
}
@ -227,6 +242,8 @@ public class DrawPaint {
switch (fill.getGradientType()) {
case linear:
return createLinearGradientPaint(fill, graphics);
case rectangular:
// TODO: implement rectangular gradient fill
case circular:
return createRadialGradientPaint(fill, graphics);
case shape:
@ -314,6 +331,8 @@ public class DrawPaint {
image = img;
}
image = colorizePattern(fill, image);
Shape s = (Shape)graphics.getRenderingHint(Drawable.GRADIENT_SHAPE);
// TODO: check why original bitmaps scale/behave differently to vector based images
@ -324,6 +343,49 @@ public class DrawPaint {
}
}
/**
* In case a duotone element is specified, handle image as pattern and replace its color values
* with the corresponding percentile / linear value between fore- and background color
*
* @return the original image if no duotone was found, otherwise the colorized pattern
*/
private static BufferedImage colorizePattern(TexturePaint fill, BufferedImage pattern) {
List<ColorStyle> duoTone = fill.getDuoTone();
if (duoTone == null || duoTone.size() != 2) {
return pattern;
}
// the pattern image is actually a gray scale image, so we simply take the first color component
// as an index into our gradient samples
int blendShades = 1 << pattern.getSampleModel().getSampleSize(0);
int[] gradSample = linearBlendedColors(duoTone, blendShades);
int[] redSample = pattern.getRaster().getSamples(0, 0, pattern.getWidth(), pattern.getHeight(), 0, (int[])null);
for (int i=0; i<redSample.length; i++) {
redSample[i] = gradSample[redSample[i] & 0xFF];
}
DirectColorModel dcm = new DirectColorModel(32, 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000);
DataBufferInt dbi = new DataBufferInt(redSample, redSample.length);
WritableRaster raster = Raster.createPackedRaster(dbi, pattern.getWidth(), pattern.getHeight(), pattern.getWidth(), new int[]{0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000}, new Point());
return new BufferedImage(dcm, raster, true, null);
}
private static int[] linearBlendedColors(List<ColorStyle> duoTone, final int blendShades) {
Color[] colors = duoTone.stream().map(DrawPaint::applyColorTransform).toArray(Color[]::new);
float[] fractions = { 0, 1 };
// create lookup list of blended colors of back- and foreground
BufferedImage gradBI = new BufferedImage(blendShades, 1, BufferedImage.TYPE_INT_ARGB);
Graphics2D gradG = gradBI.createGraphics();
gradG.setPaint(new LinearGradientPaint(0,0, blendShades,0, fractions, colors));
gradG.fillRect(0,0, blendShades,1);
gradG.dispose();
return gradBI.getRGB(0, 0, blendShades, 1, null, 0, blendShades);
}
/**
* Convert color transformations in {@link ColorStyle} to a {@link Color} instance
*
@ -341,7 +403,8 @@ public class DrawPaint {
Color result = color.getColor();
double alpha = getAlpha(result, color);
double[] hsl = RGB2HSL(result); // values are in the range [0..100] (usually ...)
// values are in the range [0..100] (usually ...)
double[] hsl = RGB2HSL(result);
applyHslModOff(hsl, 0, color.getHueMod(), color.getHueOff());
applyHslModOff(hsl, 1, color.getSatMod(), color.getSatOff());
applyHslModOff(hsl, 2, color.getLumMod(), color.getLumOff());
@ -386,16 +449,11 @@ public class DrawPaint {
* @param off the offset adjustment
*/
private static void applyHslModOff(double[] hsl, int hslPart, int mod, int off) {
if (mod == -1) {
mod = 100000;
if (mod != -1) {
hsl[hslPart] *= mod / 100_000d;
}
if (off == -1) {
off = 0;
}
if (!(mod == 100000 && off == 0)) {
double fOff = off / 1000d;
double fMod = mod / 100000d;
hsl[hslPart] = hsl[hslPart]*fMod+fOff;
if (off != -1) {
hsl[hslPart] += off / 1000d;
}
}
@ -410,9 +468,8 @@ public class DrawPaint {
return;
}
double shadePct = shade / 100000.;
hsl[2] *= 1. - shadePct;
double shadePct = shade / 100_000.;
hsl[2] *= shadePct;
}
/**
@ -423,13 +480,23 @@ public class DrawPaint {
*/
private static void applyTint(double[] hsl, ColorStyle fc) {
int tint = fc.getTint();
if (tint == -1) {
if (tint == -1 || tint == 0) {
return;
}
// see 18.8.19 fgColor (Foreground Color)
double tintPct = tint / 100000.;
hsl[2] = hsl[2]*(1.-tintPct) + (100.-100.*(1.-tintPct));
double tintPct = tint / 100_000.;
// The tint value is stored as a double from -1.0 .. 1.0, where -1.0 means 100% darken
// and 1.0 means 100% lighten. Also, 0.0 means no change.
if (tintPct < 0) {
// Lum = Lum * (1.0 + tint)
hsl[2] *= (1 + tintPct);
} else {
// Lum = Lum * (1.0-tint) + (HLSMAX HLSMAX * (1.0-tint))
hsl[2] = hsl[2]*(1-tintPct) + (100-100*(1-tintPct));
}
}
@SuppressWarnings("WeakerAccess")
@ -444,6 +511,9 @@ public class DrawPaint {
}
Rectangle2D anchor = DrawShape.getAnchor(graphics, shape);
if (anchor == null) {
return TRANSPARENT;
}
angle = convertOoxml2AwtAngle(-angle, anchor.getWidth(), anchor.getHeight());
@ -467,12 +537,50 @@ public class DrawPaint {
@SuppressWarnings("WeakerAccess")
protected Paint createRadialGradientPaint(GradientPaint fill, Graphics2D graphics) {
Rectangle2D anchor = DrawShape.getAnchor(graphics, shape);
if (anchor == null) {
return TRANSPARENT;
}
final Point2D pCenter = new Point2D.Double(anchor.getCenterX(), anchor.getCenterY());
Insets2D insets = fill.getFillToInsets();
if (insets == null) {
insets = new Insets2D(0,0,0,0);
}
// TODO: handle negative width/height
final Point2D pCenter = new Point2D.Double(
anchor.getCenterX(), anchor.getCenterY()
);
final Point2D pFocus = new Point2D.Double(
getCenterVal(anchor.getMinX(), anchor.getMaxX(), insets.left, insets.right),
getCenterVal(anchor.getMinY(), anchor.getMaxY(), insets.top, insets.bottom)
);
final float radius = (float)Math.max(anchor.getWidth(), anchor.getHeight());
return safeFractions((f,c)->new RadialGradientPaint(pCenter,radius,f,c), fill);
final AffineTransform at = new AffineTransform();
at.translate(pFocus.getX(), pFocus.getY());
at.scale(
getScale(anchor.getMinX(), anchor.getMaxX(), insets.left, insets.right),
getScale(anchor.getMinY(), anchor.getMaxY(), insets.top, insets.bottom)
);
at.translate(-pFocus.getX(), -pFocus.getY());
return safeFractions((f,c)->new RadialGradientPaint(pCenter, radius, pFocus, f, c, CycleMethod.NO_CYCLE, ColorSpaceType.SRGB, at), fill);
}
private static double getScale(double absMin, double absMax, double relMin, double relMax) {
double absDelta = absMax-absMin;
double absStart = absMin+absDelta*relMin;
double absStop = (relMin+relMax <= 1) ? absMax-absDelta*relMax : absMax+absDelta*relMax;
return (absDelta == 0) ? 1 : (absStop-absStart)/absDelta;
}
private static double getCenterVal(double absMin, double absMax, double relMin, double relMax) {
double absDelta = absMax-absMin;
double absStart = absMin+absDelta*relMin;
double absStop = (relMin+relMax <= 1) ? absMax-absDelta*relMax : absMax+absDelta*relMax;
return absStart+(absStop-absStart)/2.;
}
@SuppressWarnings({"WeakerAccess", "unused"})
@ -483,29 +591,25 @@ public class DrawPaint {
}
private Paint safeFractions(BiFunction<float[],Color[],Paint> init, GradientPaint fill) {
float[] fractions = fill.getGradientFractions();
final ColorStyle[] styles = fill.getGradientColors();
// if style is null, use transparent color to get color of background
final Iterator<Color> styles = Stream.of(fill.getGradientColors())
.map(s -> s == null ? TRANSPARENT : applyColorTransform(s))
.iterator();
// need to remap the fractions, because Java doesn't like repeating fraction values
Map<Float,Color> m = new TreeMap<>();
for (int i = 0; i<fractions.length; i++) {
// if fc is null, use transparent color to get color of background
m.put(fractions[i], (styles[i] == null ? TRANSPARENT : applyColorTransform(styles[i])));
for (float fraction : fill.getGradientFractions()) {
m.put(fraction, styles.next());
}
final Color[] colors = new Color[m.size()];
if (fractions.length != m.size()) {
fractions = new float[m.size()];
return init.apply(toArray(m.keySet()), m.values().toArray(new Color[0]));
}
int i=0;
for (Map.Entry<Float,Color> me : m.entrySet()) {
fractions[i] = me.getKey();
colors[i] = me.getValue();
i++;
}
return init.apply(fractions, colors);
private static float[] toArray(Collection<Float> floatList) {
int[] idx = { 0 };
float[] ret = new float[floatList.size()];
floatList.forEach(f -> ret[idx[0]++] = f);
return ret;
}
/**

View File

@ -20,7 +20,7 @@ package org.apache.poi.sl.usermodel;
import java.awt.geom.Dimension2D;
import java.awt.geom.Point2D;
import java.io.InputStream;
import java.util.List;
public interface PaintStyle {
@ -87,7 +87,7 @@ public interface PaintStyle {
}
interface GradientPaint extends PaintStyle {
enum GradientType { linear, circular, shape }
enum GradientType { linear, circular, rectangular, shape }
/**
* @return the angle of the gradient
@ -97,6 +97,10 @@ public interface PaintStyle {
float[] getGradientFractions();
boolean isRotatedWithShape();
GradientType getGradientType();
default Insets2D getFillToInsets() {
return null;
}
}
interface TexturePaint extends PaintStyle {
@ -170,5 +174,14 @@ public interface PaintStyle {
default Insets2D getStretch() {
return null;
}
/**
* For pattern images, the duo tone defines the black/white pixel color replacement
*/
default List<ColorStyle> getDuoTone() {
return null;
}
}
}

View File

@ -106,7 +106,7 @@ public class XSLFBackground extends XSLFSimpleShape
CTSolidColorFillProperties fill = bgPr.isSetSolidFill() ? bgPr.getSolidFill() : bgPr.addNewSolidFill();
XSLFColor col = new XSLFColor(fill, getSheet().getTheme(), fill.getSchemeClr());
XSLFColor col = new XSLFColor(fill, getSheet().getTheme(), fill.getSchemeClr(), getSheet());
col.setColor(color);
}
}

View File

@ -19,6 +19,9 @@
package org.apache.poi.xslf.usermodel;
import java.awt.Color;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.apache.poi.sl.draw.DrawPaint;
import org.apache.poi.sl.usermodel.AbstractColorStyle;
@ -52,11 +55,13 @@ public class XSLFColor {
private XmlObject _xmlObject;
private Color _color;
private CTSchemeColor _phClr;
private XSLFSheet _sheet;
@SuppressWarnings("WeakerAccess")
public XSLFColor(XmlObject obj, XSLFTheme theme, CTSchemeColor phClr) {
public XSLFColor(XmlObject obj, XSLFTheme theme, CTSchemeColor phClr, XSLFSheet sheet) {
_xmlObject = obj;
_phClr = phClr;
_sheet = sheet;
_color = toColor(obj, theme);
}
@ -74,117 +79,88 @@ public class XSLFColor {
return DrawPaint.applyColorTransform(getColorStyle());
}
@SuppressWarnings("WeakerAccess")
public ColorStyle getColorStyle() {
return new AbstractColorStyle() {
@Override
public Color getColor() {
return _color;
return new XSLFColorStyle(_xmlObject, _color, _phClr);
}
@Override
public int getAlpha() {
return getRawValue("alpha");
private Color toColor(CTHslColor hsl) {
return DrawPaint.HSL2RGB(
hsl.getHue2() / 60000d,
hsl.getSat2() / 1000d,
hsl.getLum2() / 1000d,
1d);
}
@Override
public int getHueOff() {
return getRawValue("hueOff");
}
@Override
public int getHueMod() {
return getRawValue("hueMod");
}
@Override
public int getSatOff() {
return getRawValue("satOff");
}
@Override
public int getSatMod() {
return getRawValue("satMod");
}
@Override
public int getLumOff() {
return getRawValue("lumOff");
}
@Override
public int getLumMod() {
return getRawValue("lumMod");
}
@Override
public int getShade() {
return getRawValue("shade");
}
@Override
public int getTint() {
return getRawValue("tint");
}
};
}
private Color toColor(XmlObject obj, XSLFTheme theme) {
Color color = null;
for (XmlObject ch : obj.selectPath("*")) {
if (ch instanceof CTHslColor) {
CTHslColor hsl = (CTHslColor)ch;
int h = hsl.getHue2();
int s = hsl.getSat2();
int l = hsl.getLum2();
color = DrawPaint.HSL2RGB(h / 60000d, s / 1000d, l / 1000d, 1d);
} else if (ch instanceof CTPresetColor) {
CTPresetColor prst = (CTPresetColor)ch;
private Color toColor(CTPresetColor prst) {
String colorName = prst.getVal().toString();
PresetColor pc = PresetColor.valueOfOoxmlId(colorName);
if (pc != null) {
color = pc.color;
return (pc != null) ? pc.color : null;
}
} else if (ch instanceof CTSchemeColor) {
CTSchemeColor schemeColor = (CTSchemeColor)ch;
private Color toColor(CTSchemeColor schemeColor, XSLFTheme theme) {
String colorRef = schemeColor.getVal().toString();
if(_phClr != null) {
// context color overrides the theme
colorRef = _phClr.getVal().toString();
}
// find referenced CTColor in the theme and convert it to java.awt.Color via a recursive call
CTColor ctColor = theme == null ? null : theme.getCTColor(colorRef);
if(ctColor != null) {
color = toColor(ctColor, null);
CTColor ctColor = theme == null ? null : theme.getCTColor(_sheet.mapSchemeColor(colorRef));
return (ctColor != null) ? toColor(ctColor, null) : null;
}
} else if (ch instanceof CTScRgbColor) {
private Color toColor(CTScRgbColor scrgb) {
// color in percentage is in linear RGB color space, i.e. needs to be gamma corrected for AWT color
CTScRgbColor scrgb = (CTScRgbColor)ch;
color = new Color(DrawPaint.lin2srgb(scrgb.getR()), DrawPaint.lin2srgb(scrgb.getG()), DrawPaint.lin2srgb(scrgb.getB()));
} else if (ch instanceof CTSRgbColor) {
return new Color(DrawPaint.lin2srgb(scrgb.getR()), DrawPaint.lin2srgb(scrgb.getG()), DrawPaint.lin2srgb(scrgb.getB()));
}
private Color toColor(CTSRgbColor srgb) {
// color in sRGB color space, i.e. same as AWT Color
CTSRgbColor srgb = (CTSRgbColor)ch;
byte[] val = srgb.getVal();
color = new Color(0xFF & val[0], 0xFF & val[1], 0xFF & val[2]);
} else if (ch instanceof CTSystemColor) {
CTSystemColor sys = (CTSystemColor)ch;
return new Color(0xFF & val[0], 0xFF & val[1], 0xFF & val[2]);
}
private Color toColor(CTSystemColor sys) {
if (sys.isSetLastClr()) {
byte[] val = sys.getLastClr();
color = new Color(0xFF & val[0], 0xFF & val[1], 0xFF & val[2]);
return new Color(0xFF & val[0], 0xFF & val[1], 0xFF & val[2]);
} else {
String colorName = sys.getVal().toString();
PresetColor pc = PresetColor.valueOfOoxmlId(colorName);
if (pc != null) {
color = pc.color;
}
if (color == null) {
color = Color.black;
return (pc != null && pc.color != null) ? pc.color : Color.black;
}
}
private Color toColor(XmlObject obj, XSLFTheme theme) {
Color color = null;
List<XmlObject> xo = new ArrayList<>();
xo.add(obj);
xo.addAll(Arrays.asList(obj.selectPath("*")));
boolean isFirst = true;
for (XmlObject ch : xo) {
if (ch instanceof CTHslColor) {
color = toColor((CTHslColor)ch);
} else if (ch instanceof CTPresetColor) {
color = toColor((CTPresetColor)ch);
} else if (ch instanceof CTSchemeColor) {
color = toColor((CTSchemeColor)ch, theme);
} else if (ch instanceof CTScRgbColor) {
color = toColor((CTScRgbColor)ch);
} else if (ch instanceof CTSRgbColor) {
color = toColor((CTSRgbColor)ch);
} else if (ch instanceof CTSystemColor) {
color = toColor((CTSystemColor)ch);
} else if (!(ch instanceof CTFontReference)) {
if (!isFirst) {
throw new IllegalArgumentException("Unexpected color choice: " + ch.getClass());
}
}
if (color != null) {
break;
}
isFirst = false;
}
return color;
}
@ -257,14 +233,14 @@ public class XSLFColor {
return Math.abs((f*255d) - Math.rint(f*255d)) < 0.00001;
}
private int getRawValue(String elem) {
private static int getRawValue(CTSchemeColor phClr, XmlObject xmlObject, String elem) {
String query = "declare namespace a='http://schemas.openxmlformats.org/drawingml/2006/main' $this//a:" + elem;
XmlObject[] obj;
// first ask the context color and if not found, ask the actual color bean
if (_phClr != null){
obj = _phClr.selectPath(query);
if (phClr != null){
obj = phClr.selectPath(query);
if (obj.length == 1){
Node attr = obj[0].getDomNode().getAttributes().getNamedItem("val");
if(attr != null) {
@ -273,7 +249,7 @@ public class XSLFColor {
}
}
obj = _xmlObject.selectPath(query);
obj = xmlObject.selectPath(query);
if (obj.length == 1){
Node attr = obj[0].getDomNode().getAttributes().getNamedItem("val");
if(attr != null) {
@ -294,7 +270,7 @@ public class XSLFColor {
* @return the percentage value in the range [0 .. 100]
*/
private int getPercentageValue(String elem){
int val = getRawValue(elem);
int val = getRawValue(_phClr, _xmlObject, elem);
return (val == -1) ? val : (val / 1000);
}
@ -333,7 +309,7 @@ public class XSLFColor {
@SuppressWarnings("unused")
int getHue(){
int val = getRawValue("hue");
int val = getRawValue(_phClr, _xmlObject, "hue");
return (val == -1) ? val : (val / 60000);
}
@ -500,4 +476,66 @@ public class XSLFColor {
public int getTint(){
return getPercentageValue("tint");
}
private static class XSLFColorStyle extends AbstractColorStyle {
private XmlObject xmlObject;
private Color color;
private CTSchemeColor phClr;
XSLFColorStyle(XmlObject xmlObject, Color color, CTSchemeColor phClr) {
this.xmlObject = xmlObject;
this.color = color;
this.phClr = phClr;
}
@Override
public Color getColor() {
return color;
}
@Override
public int getAlpha() {
return getRawValue(phClr, xmlObject, "alpha");
}
@Override
public int getHueOff() {
return getRawValue(phClr, xmlObject, "hueOff");
}
@Override
public int getHueMod() {
return getRawValue(phClr, xmlObject, "hueMod");
}
@Override
public int getSatOff() {
return getRawValue(phClr, xmlObject, "satOff");
}
@Override
public int getSatMod() {
return getRawValue(phClr, xmlObject, "satMod");
}
@Override
public int getLumOff() {
return getRawValue(phClr, xmlObject, "lumOff");
}
@Override
public int getLumMod() {
return getRawValue(phClr, xmlObject, "lumMod");
}
@Override
public int getShade() {
return getRawValue(phClr, xmlObject, "shade");
}
@Override
public int getTint() {
return getRawValue(phClr, xmlObject, "tint");
}
}
}

View File

@ -20,10 +20,12 @@ package org.apache.poi.xslf.usermodel;
import java.util.Arrays;
import org.apache.poi.sl.usermodel.ColorStyle;
import org.apache.poi.sl.usermodel.Insets2D;
import org.apache.poi.sl.usermodel.PaintStyle;
import org.apache.poi.util.Internal;
import org.openxmlformats.schemas.drawingml.x2006.main.CTGradientFillProperties;
import org.openxmlformats.schemas.drawingml.x2006.main.CTGradientStop;
import org.openxmlformats.schemas.drawingml.x2006.main.CTRelativeRect;
import org.openxmlformats.schemas.drawingml.x2006.main.CTSchemeColor;
import org.openxmlformats.schemas.drawingml.x2006.main.STPathShadeType;
@ -34,7 +36,7 @@ public class XSLFGradientPaint implements PaintStyle.GradientPaint {
final ColorStyle[] cs;
final float[] fractions;
public XSLFGradientPaint(final CTGradientFillProperties gradFill, CTSchemeColor phClr, final XSLFTheme theme) {
public XSLFGradientPaint(final CTGradientFillProperties gradFill, CTSchemeColor phClr, final XSLFTheme theme, final XSLFSheet sheet) {
this.gradFill = gradFill;
final CTGradientStop[] gs = gradFill.getGsLst() == null ?
@ -55,7 +57,7 @@ public class XSLFGradientPaint implements PaintStyle.GradientPaint {
if (phClrCgs == null && cgs.isSetSchemeClr()) {
phClrCgs = cgs.getSchemeClr();
}
cs[i] = new XSLFColor(cgs, theme, phClrCgs).getColorStyle();
cs[i] = new XSLFColor(cgs, theme, phClrCgs, sheet).getColorStyle();
fractions[i] = cgs.getPos() / 100000.f;
i++;
}
@ -98,10 +100,21 @@ public class XSLFGradientPaint implements PaintStyle.GradientPaint {
return PaintStyle.GradientPaint.GradientType.circular;
} else if (ps == STPathShadeType.SHAPE) {
return PaintStyle.GradientPaint.GradientType.shape;
} else if (ps == STPathShadeType.RECT) {
return PaintStyle.GradientPaint.GradientType.rectangular;
}
}
return PaintStyle.GradientPaint.GradientType.linear;
}
@Override
public Insets2D getFillToInsets() {
if (gradFill.isSetPath() && gradFill.getPath().isSetFillToRect()) {
final double base = 100_000;
CTRelativeRect rect = gradFill.getPath().getFillToRect();
return new Insets2D(rect.getT()/base, rect.getL()/base, rect.getB()/base, rect.getR()/base);
}
return null;
}
}

View File

@ -40,7 +40,6 @@ implements Notes<XSLFShape,XSLFTextParagraph> {
* Create a new notes
*/
XSLFNotes() {
super();
_notes = prototype();
}
@ -105,4 +104,9 @@ implements Notes<XSLFShape,XSLFTextParagraph> {
}
return tp;
}
@Override
String mapSchemeColor(String schemeColor) {
return mapSchemeColor(_notes.getClrMapOvr(), schemeColor);
}
}

View File

@ -26,7 +26,6 @@ import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.sl.usermodel.MasterSheet;
import org.apache.poi.util.Beta;
import org.apache.xmlbeans.XmlException;
import org.openxmlformats.schemas.drawingml.x2006.main.CTColorMapping;
import org.openxmlformats.schemas.presentationml.x2006.main.CTNotesMaster;
import org.openxmlformats.schemas.presentationml.x2006.main.NotesMasterDocument;
@ -106,7 +105,8 @@ import org.openxmlformats.schemas.presentationml.x2006.main.NotesMasterDocument;
}
@Override
CTColorMapping getColorMapping() {
return _slide.getClrMap();
String mapSchemeColor(String schemeColor) {
String notesMasterColor = mapSchemeColor(_slide.getClrMap(), schemeColor);
return notesMasterColor == null ? schemeColor : notesMasterColor;
}
}

View File

@ -100,7 +100,7 @@ public class XSLFShadow extends XSLFShape implements Shadow<XSLFShape,XSLFTextPa
if(ct == null) return null;
CTSchemeColor phClr = ct.getSchemeClr();
final XSLFColor xc = new XSLFColor(ct, theme, phClr);
final XSLFColor xc = new XSLFColor(ct, theme, phClr, getSheet());
return DrawPaint.createSolidPaint(xc.getColorStyle());
}
}

View File

@ -144,7 +144,7 @@ public abstract class XSLFShape implements Shape<XSLFShape,XSLFTextParagraph> {
if (shape instanceof XSLFPictureShape) {
CTPicture pic = (CTPicture)shape.getXmlObject();
if (pic.getBlipFill() != null) {
setValue(selectPaint(pic.getBlipFill(), pp));
setValue(selectPaint(pic.getBlipFill(), pp, null, theme));
return true;
}
}
@ -360,13 +360,13 @@ public abstract class XSLFShape implements Shape<XSLFShape,XSLFTextParagraph> {
* @return the applied Paint or null if none was applied
*/
@SuppressWarnings("WeakerAccess")
protected static PaintStyle selectPaint(XSLFFillProperties fp, final CTSchemeColor phClr, final PackagePart parentPart, final XSLFTheme theme, boolean hasPlaceholder) {
protected PaintStyle selectPaint(XSLFFillProperties fp, final CTSchemeColor phClr, final PackagePart parentPart, final XSLFTheme theme, boolean hasPlaceholder) {
if (fp == null || fp.isSetNoFill()) {
return null;
} else if (fp.isSetSolidFill()) {
return selectPaint(fp.getSolidFill(), phClr, theme);
} else if (fp.isSetBlipFill()) {
return selectPaint(fp.getBlipFill(), parentPart);
return selectPaint(fp.getBlipFill(), parentPart, phClr, theme);
} else if (fp.isSetGradFill()) {
return selectPaint(fp.getGradFill(), phClr, theme);
} else if (fp.isSetMatrixStyle()) {
@ -377,7 +377,7 @@ public abstract class XSLFShape implements Shape<XSLFShape,XSLFTextParagraph> {
}
@SuppressWarnings("WeakerAccess")
protected static PaintStyle selectPaint(CTSolidColorFillProperties solidFill, CTSchemeColor phClr, final XSLFTheme theme) {
protected PaintStyle selectPaint(CTSolidColorFillProperties solidFill, CTSchemeColor phClr, final XSLFTheme theme) {
if (solidFill.isSetSchemeClr()) {
// if there's a reference to the placeholder color,
// stop evaluating further and let the caller select
@ -389,22 +389,22 @@ public abstract class XSLFShape implements Shape<XSLFShape,XSLFTextParagraph> {
phClr = solidFill.getSchemeClr();
}
}
final XSLFColor c = new XSLFColor(solidFill, theme, phClr);
final XSLFColor c = new XSLFColor(solidFill, theme, phClr, _sheet);
return DrawPaint.createSolidPaint(c.getColorStyle());
}
@SuppressWarnings("WeakerAccess")
protected static PaintStyle selectPaint(final CTBlipFillProperties blipFill, final PackagePart parentPart) {
return new XSLFTexturePaint(blipFill, parentPart);
protected PaintStyle selectPaint(final CTBlipFillProperties blipFill, final PackagePart parentPart, CTSchemeColor phClr, final XSLFTheme theme) {
return new XSLFTexturePaint(blipFill, parentPart, phClr, theme, _sheet);
}
@SuppressWarnings("WeakerAccess")
protected static PaintStyle selectPaint(final CTGradientFillProperties gradFill, CTSchemeColor phClr, final XSLFTheme theme) {
return new XSLFGradientPaint(gradFill, phClr, theme);
protected PaintStyle selectPaint(final CTGradientFillProperties gradFill, CTSchemeColor phClr, final XSLFTheme theme) {
return new XSLFGradientPaint(gradFill, phClr, theme, _sheet);
}
@SuppressWarnings("WeakerAccess")
protected static PaintStyle selectPaint(CTStyleMatrixReference fillRef, final XSLFTheme theme, boolean isLineStyle, boolean hasPlaceholder) {
protected PaintStyle selectPaint(CTStyleMatrixReference fillRef, final XSLFTheme theme, boolean isLineStyle, boolean hasPlaceholder) {
if (fillRef == null) {
return null;
}
@ -441,7 +441,7 @@ public abstract class XSLFShape implements Shape<XSLFShape,XSLFTextParagraph> {
if (res != null || hasPlaceholder) {
return res;
}
XSLFColor col = new XSLFColor(fillRef, theme, phClr);
XSLFColor col = new XSLFColor(fillRef, theme, phClr, _sheet);
return DrawPaint.createSolidPaint(col.getColorStyle());
}

View File

@ -29,7 +29,6 @@ import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import javax.xml.namespace.QName;
@ -60,6 +59,8 @@ import org.apache.xmlbeans.XmlObject;
import org.apache.xmlbeans.XmlOptions;
import org.apache.xmlbeans.impl.values.XmlAnyTypeImpl;
import org.openxmlformats.schemas.drawingml.x2006.main.CTColorMapping;
import org.openxmlformats.schemas.drawingml.x2006.main.CTColorMappingOverride;
import org.openxmlformats.schemas.drawingml.x2006.main.STColorSchemeIndex;
import org.openxmlformats.schemas.presentationml.x2006.main.CTConnector;
import org.openxmlformats.schemas.presentationml.x2006.main.CTGraphicalObjectFrame;
import org.openxmlformats.schemas.presentationml.x2006.main.CTGroupShape;
@ -497,15 +498,11 @@ implements XSLFShapeContainer, Sheet<XSLFShape,XSLFTextParagraph> {
return _theme;
}
final Optional<XSLFTheme> t =
getRelations().stream().filter((p) -> p instanceof XSLFTheme).map((p) -> (XSLFTheme) p).findAny();
if (t.isPresent()) {
_theme = t.get();
final CTColorMapping cmap = getColorMapping();
if (cmap != null) {
_theme.initColorMap(cmap);
}
}
getRelations().stream()
.filter(p -> p instanceof XSLFTheme)
.findAny()
.ifPresent(p -> _theme = (XSLFTheme)p);
return _theme;
}
@ -521,7 +518,7 @@ implements XSLFShapeContainer, Sheet<XSLFShape,XSLFTextParagraph> {
/**
* @return the color mapping for this slide type
*/
CTColorMapping getColorMapping() {
String mapSchemeColor(String schemeColor) {
return null;
}
@ -744,4 +741,60 @@ implements XSLFShapeContainer, Sheet<XSLFShape,XSLFTextParagraph> {
getDrawing().addChart(rp.getRelationship().getId(), rect2D);
}
protected String mapSchemeColor(CTColorMappingOverride cmapOver, String schemeColor) {
String slideColor = mapSchemeColor((cmapOver == null) ? null : cmapOver.getOverrideClrMapping(), schemeColor);
if (slideColor != null) {
return slideColor;
}
XSLFSheet master = (XSLFSheet)getMasterSheet();
String masterColor = (master == null) ? null : master.mapSchemeColor(schemeColor);
return (masterColor == null) ? schemeColor : masterColor;
}
protected String mapSchemeColor(CTColorMapping cmap, String schemeColor) {
STColorSchemeIndex.Enum schemeMap = null;
if (cmap != null && schemeColor != null) {
switch (schemeColor) {
case "accent1":
schemeMap = cmap.getAccent1();
break;
case "accent2":
schemeMap = cmap.getAccent2();
break;
case "accent3":
schemeMap = cmap.getAccent3();
break;
case "accent4":
schemeMap = cmap.getAccent4();
break;
case "accent5":
schemeMap = cmap.getAccent5();
break;
case "accent6":
schemeMap = cmap.getAccent6();
break;
case "bg1":
schemeMap = cmap.getBg1();
break;
case "bg2":
schemeMap = cmap.getBg2();
break;
case "folHlink":
schemeMap = cmap.getFolHlink();
break;
case "hlink":
schemeMap = cmap.getHlink();
break;
case "tx1":
schemeMap = cmap.getTx1();
break;
case "tx2":
schemeMap = cmap.getTx2();
break;
default:
break;
}
}
return (schemeMap == null) ? null : schemeMap.toString();
}
}

View File

@ -51,33 +51,7 @@ import org.apache.poi.xslf.usermodel.XSLFPropertiesDelegate.XSLFEffectProperties
import org.apache.poi.xslf.usermodel.XSLFPropertiesDelegate.XSLFFillProperties;
import org.apache.poi.xslf.usermodel.XSLFPropertiesDelegate.XSLFGeometryProperties;
import org.apache.xmlbeans.XmlObject;
import org.openxmlformats.schemas.drawingml.x2006.main.CTBaseStyles;
import org.openxmlformats.schemas.drawingml.x2006.main.CTBlip;
import org.openxmlformats.schemas.drawingml.x2006.main.CTEffectStyleItem;
import org.openxmlformats.schemas.drawingml.x2006.main.CTGeomGuide;
import org.openxmlformats.schemas.drawingml.x2006.main.CTLineEndProperties;
import org.openxmlformats.schemas.drawingml.x2006.main.CTLineProperties;
import org.openxmlformats.schemas.drawingml.x2006.main.CTLineStyleList;
import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps;
import org.openxmlformats.schemas.drawingml.x2006.main.CTOuterShadowEffect;
import org.openxmlformats.schemas.drawingml.x2006.main.CTPoint2D;
import org.openxmlformats.schemas.drawingml.x2006.main.CTPositiveSize2D;
import org.openxmlformats.schemas.drawingml.x2006.main.CTPresetGeometry2D;
import org.openxmlformats.schemas.drawingml.x2006.main.CTPresetLineDashProperties;
import org.openxmlformats.schemas.drawingml.x2006.main.CTSchemeColor;
import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeProperties;
import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeStyle;
import org.openxmlformats.schemas.drawingml.x2006.main.CTSolidColorFillProperties;
import org.openxmlformats.schemas.drawingml.x2006.main.CTStyleMatrix;
import org.openxmlformats.schemas.drawingml.x2006.main.CTStyleMatrixReference;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTransform2D;
import org.openxmlformats.schemas.drawingml.x2006.main.STCompoundLine;
import org.openxmlformats.schemas.drawingml.x2006.main.STLineCap;
import org.openxmlformats.schemas.drawingml.x2006.main.STLineEndLength;
import org.openxmlformats.schemas.drawingml.x2006.main.STLineEndType;
import org.openxmlformats.schemas.drawingml.x2006.main.STLineEndWidth;
import org.openxmlformats.schemas.drawingml.x2006.main.STPresetLineDashVal;
import org.openxmlformats.schemas.drawingml.x2006.main.STShapeType;
import org.openxmlformats.schemas.drawingml.x2006.main.*;
/**
* Represents a single (non-group) shape in a .pptx slide show
@ -291,7 +265,7 @@ public abstract class XSLFSimpleShape extends XSLFShape
ln.addNewNoFill();
} else {
CTSolidColorFillProperties fill = ln.addNewSolidFill();
XSLFColor col = new XSLFColor(fill, getSheet().getTheme(), fill.getSchemeClr());
XSLFColor col = new XSLFColor(fill, getSheet().getTheme(), fill.getSchemeClr(), getSheet());
col.setColor(color);
}
}
@ -664,7 +638,7 @@ public abstract class XSLFSimpleShape extends XSLFShape
CTSolidColorFillProperties fill = fp.isSetSolidFill() ? fp.getSolidFill() : fp.addNewSolidFill();
XSLFColor col = new XSLFColor(fill, getSheet().getTheme(), fill.getSchemeClr());
XSLFColor col = new XSLFColor(fill, getSheet().getTheme(), fill.getSchemeClr(), getSheet());
col.setColor(color);
}
}

View File

@ -24,6 +24,7 @@ import java.util.ArrayList;
import java.util.List;
import org.apache.poi.ooxml.POIXMLDocumentPart;
import org.apache.poi.ooxml.util.DocumentHelper;
import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.sl.draw.DrawFactory;
import org.apache.poi.sl.draw.Drawable;
@ -31,7 +32,6 @@ import org.apache.poi.sl.usermodel.Notes;
import org.apache.poi.sl.usermodel.Placeholder;
import org.apache.poi.sl.usermodel.Slide;
import org.apache.poi.util.Beta;
import org.apache.poi.ooxml.util.DocumentHelper;
import org.apache.poi.util.NotImplemented;
import org.apache.xmlbeans.XmlException;
import org.openxmlformats.schemas.drawingml.x2006.main.CTGroupShapeProperties;
@ -403,4 +403,9 @@ implements Slide<XSLFShape,XSLFTextParagraph> {
final CTCommonSlideData cSld = getXmlObject().getCSld();
return cSld.isSetName() ? cSld.getName() : "Slide"+getSlideNumber();
}
@Override
String mapSchemeColor(String schemeColor) {
return mapSchemeColor(_slide.getClrMapOvr(), schemeColor);
}
}

View File

@ -145,4 +145,10 @@ implements MasterSheet<XSLFShape,XSLFTextParagraph> {
int ordinal = _layout.getType().intValue() - 1;
return SlideLayout.values()[ordinal];
}
@Override
String mapSchemeColor(String schemeColor) {
return mapSchemeColor(_layout.getClrMapOvr(), schemeColor);
}
}

View File

@ -29,7 +29,6 @@ import org.apache.poi.sl.usermodel.MasterSheet;
import org.apache.poi.sl.usermodel.Placeholder;
import org.apache.poi.util.Beta;
import org.apache.xmlbeans.XmlException;
import org.openxmlformats.schemas.drawingml.x2006.main.CTColorMapping;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextListStyle;
import org.openxmlformats.schemas.presentationml.x2006.main.CTBackground;
import org.openxmlformats.schemas.presentationml.x2006.main.CTSlideMaster;
@ -169,7 +168,8 @@ import org.openxmlformats.schemas.presentationml.x2006.main.SldMasterDocument;
}
@Override
CTColorMapping getColorMapping() {
return _slide.getClrMap();
String mapSchemeColor(String schemeColor) {
String masterColor = mapSchemeColor(_slide.getClrMap(), schemeColor);
return masterColor == null ? schemeColor : masterColor;
}
}

View File

@ -37,33 +37,7 @@ import org.apache.poi.xddf.usermodel.text.XDDFTextBody;
import org.apache.poi.xslf.usermodel.XSLFPropertiesDelegate.XSLFFillProperties;
import org.apache.poi.xslf.usermodel.XSLFTableStyle.TablePartStyle;
import org.apache.xmlbeans.XmlObject;
import org.openxmlformats.schemas.drawingml.x2006.main.CTFontReference;
import org.openxmlformats.schemas.drawingml.x2006.main.CTLineEndProperties;
import org.openxmlformats.schemas.drawingml.x2006.main.CTLineProperties;
import org.openxmlformats.schemas.drawingml.x2006.main.CTPoint2D;
import org.openxmlformats.schemas.drawingml.x2006.main.CTPositiveSize2D;
import org.openxmlformats.schemas.drawingml.x2006.main.CTSchemeColor;
import org.openxmlformats.schemas.drawingml.x2006.main.CTSolidColorFillProperties;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTable;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTableCell;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTableCellProperties;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTablePartStyle;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTableProperties;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTableStyleCellStyle;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTableStyleTextStyle;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextBody;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraph;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTransform2D;
import org.openxmlformats.schemas.drawingml.x2006.main.STCompoundLine;
import org.openxmlformats.schemas.drawingml.x2006.main.STLineCap;
import org.openxmlformats.schemas.drawingml.x2006.main.STLineEndLength;
import org.openxmlformats.schemas.drawingml.x2006.main.STLineEndType;
import org.openxmlformats.schemas.drawingml.x2006.main.STLineEndWidth;
import org.openxmlformats.schemas.drawingml.x2006.main.STOnOffStyleType;
import org.openxmlformats.schemas.drawingml.x2006.main.STPenAlignment;
import org.openxmlformats.schemas.drawingml.x2006.main.STPresetLineDashVal;
import org.openxmlformats.schemas.drawingml.x2006.main.STTextAnchoringType;
import org.openxmlformats.schemas.drawingml.x2006.main.STTextVerticalType;
import org.openxmlformats.schemas.drawingml.x2006.main.*;
/**
* Represents a cell of a table in a .pptx presentation
@ -319,7 +293,7 @@ public class XSLFTableCell extends XSLFTextShape implements TableCell<XSLFShape,
CTLineProperties ln = setBorderDefaults(edge);
CTSolidColorFillProperties fill = ln.addNewSolidFill();
XSLFColor c = new XSLFColor(fill, getSheet().getTheme(), fill.getSchemeClr());
XSLFColor c = new XSLFColor(fill, getSheet().getTheme(), fill.getSchemeClr(), getSheet());
c.setColor(color);
}
@ -331,7 +305,7 @@ public class XSLFTableCell extends XSLFTextShape implements TableCell<XSLFShape,
}
CTSolidColorFillProperties fill = ln.getSolidFill();
XSLFColor c = new XSLFColor(fill, getSheet().getTheme(), fill.getSchemeClr());
XSLFColor c = new XSLFColor(fill, getSheet().getTheme(), fill.getSchemeClr(), getSheet());
return c.getColor();
}
@ -415,7 +389,7 @@ public class XSLFTableCell extends XSLFTextShape implements TableCell<XSLFShape,
}
} else {
CTSolidColorFillProperties fill = spPr.isSetSolidFill() ? spPr.getSolidFill() : spPr.addNewSolidFill();
XSLFColor c = new XSLFColor(fill, getSheet().getTheme(), fill.getSchemeClr());
XSLFColor c = new XSLFColor(fill, getSheet().getTheme(), fill.getSchemeClr(), getSheet());
c.setColor(color);
}
}
@ -470,7 +444,7 @@ public class XSLFTableCell extends XSLFTextShape implements TableCell<XSLFShape,
fp = XSLFPropertiesDelegate.getFillDelegate(props);
if (fp != null) {
PaintStyle paint = XSLFShape.selectPaint(fp, null, slideShow.getPackagePart(), theme, hasPlaceholder);
PaintStyle paint = selectPaint(fp, null, slideShow.getPackagePart(), theme, hasPlaceholder);
if (paint != null) {
return paint;
}
@ -758,7 +732,7 @@ public class XSLFTableCell extends XSLFTextShape implements TableCell<XSLFShape,
}
XSLFTheme theme = getSheet().getTheme();
final XSLFColor c = new XSLFColor(txStyle, theme, phClr);
final XSLFColor c = new XSLFColor(txStyle, theme, phClr, getSheet());
return DrawPaint.createSolidPaint(c.getColorStyle());
}

View File

@ -279,7 +279,7 @@ public class XSLFTextParagraph implements TextParagraph<XSLFShape,XSLFTextParagr
@Override
public boolean fetch(CTTextParagraphProperties props){
if(props.isSetBuClr()){
XSLFColor c = new XSLFColor(props.getBuClr(), theme, null);
XSLFColor c = new XSLFColor(props.getBuClr(), theme, null, _shape.getSheet());
setValue(c.getColor());
return true;
}

View File

@ -123,7 +123,8 @@ public class XSLFTextRun implements TextRun {
CTTextCharacterProperties rPr = getRPr(true);
CTSolidColorFillProperties fill = rPr.isSetSolidFill() ? rPr.getSolidFill() : rPr.addNewSolidFill();
XSLFColor col = new XSLFColor(fill, getParentParagraph().getParentShape().getSheet().getTheme(), fill.getSchemeClr());
XSLFSheet sheet = getParentParagraph().getParentShape().getSheet();
XSLFColor col = new XSLFColor(fill, sheet.getTheme(), fill.getSchemeClr(), sheet);
col.setColor(c);
}
@ -148,7 +149,7 @@ public class XSLFTextRun implements TextRun {
XSLFSheet sheet = shape.getSheet();
PackagePart pp = sheet.getPackagePart();
XSLFTheme theme = sheet.getTheme();
PaintStyle ps = XSLFShape.selectPaint(fp, phClr, pp, theme, hasPlaceholder);
PaintStyle ps = shape.selectPaint(fp, phClr, pp, theme, hasPlaceholder);
if (ps != null) {
setValue(ps);

View File

@ -21,11 +21,14 @@ import java.awt.geom.Dimension2D;
import java.awt.geom.Point2D;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Supplier;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.openxml4j.opc.PackageRelationship;
import org.apache.poi.sl.usermodel.ColorStyle;
import org.apache.poi.sl.usermodel.Insets2D;
import org.apache.poi.sl.usermodel.PaintStyle;
import org.apache.poi.util.Dimension2DDouble;
@ -33,7 +36,9 @@ import org.apache.poi.util.Internal;
import org.apache.poi.util.Units;
import org.openxmlformats.schemas.drawingml.x2006.main.CTBlip;
import org.openxmlformats.schemas.drawingml.x2006.main.CTBlipFillProperties;
import org.openxmlformats.schemas.drawingml.x2006.main.CTDuotoneEffect;
import org.openxmlformats.schemas.drawingml.x2006.main.CTRelativeRect;
import org.openxmlformats.schemas.drawingml.x2006.main.CTSchemeColor;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTileInfoProperties;
import org.openxmlformats.schemas.drawingml.x2006.main.STTileFlipMode;
@ -42,11 +47,17 @@ public class XSLFTexturePaint implements PaintStyle.TexturePaint {
private final CTBlipFillProperties blipFill;
private final PackagePart parentPart;
private final CTBlip blip;
private final CTSchemeColor phClr;
private final XSLFTheme theme;
private final XSLFSheet sheet;
public XSLFTexturePaint(final CTBlipFillProperties blipFill, final PackagePart parentPart) {
public XSLFTexturePaint(final CTBlipFillProperties blipFill, final PackagePart parentPart, CTSchemeColor phClr, final XSLFTheme theme, final XSLFSheet sheet) {
this.blipFill = blipFill;
this.parentPart = parentPart;
blip = blipFill.getBlip();
this.phClr = phClr;
this.theme = theme;
this.sheet = sheet;
}
@ -139,6 +150,20 @@ public class XSLFTexturePaint implements PaintStyle.TexturePaint {
return getRectVal(blipFill.isSetStretch() ? blipFill.getStretch().getFillRect() : null);
}
@Override
public List<ColorStyle> getDuoTone() {
if (blip.sizeOfDuotoneArray() == 0) {
return null;
}
List<ColorStyle> colors = new ArrayList<>();
CTDuotoneEffect duoEff = blip.getDuotoneArray(0);
for (CTSchemeColor phClrDuo : duoEff.getSchemeClrArray()) {
colors.add(new XSLFColor(phClrDuo, theme, phClr, sheet).getColorStyle());
}
return colors;
}
private static Insets2D getRectVal(CTRelativeRect rect) {
return rect == null ? null : new Insets2D(
getRectVal(rect::isSetT, rect::getT),

View File

@ -20,8 +20,6 @@ import static org.apache.poi.ooxml.POIXMLTypeLoader.DEFAULT_XML_OPTIONS;
import java.io.IOException;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Map;
import javax.xml.namespace.QName;
@ -30,27 +28,21 @@ import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.util.Beta;
import org.apache.poi.util.Internal;
import org.apache.xmlbeans.XmlException;
import org.apache.xmlbeans.XmlObject;
import org.apache.xmlbeans.XmlOptions;
import org.openxmlformats.schemas.drawingml.x2006.main.CTBaseStyles;
import org.openxmlformats.schemas.drawingml.x2006.main.CTColor;
import org.openxmlformats.schemas.drawingml.x2006.main.CTColorMapping;
import org.openxmlformats.schemas.drawingml.x2006.main.CTColorScheme;
import org.openxmlformats.schemas.drawingml.x2006.main.CTOfficeStyleSheet;
import org.openxmlformats.schemas.drawingml.x2006.main.ThemeDocument;
/**
* A shared style sheet in a .pptx slide show
*
* @author Yegor Kozlov
*/
@Beta
public class XSLFTheme extends POIXMLDocumentPart {
private CTOfficeStyleSheet _theme;
private Map<String, CTColor> _schemeColors;
XSLFTheme() {
super();
_theme = CTOfficeStyleSheet.Factory.newInstance();
}
@ -62,37 +54,11 @@ public class XSLFTheme extends POIXMLDocumentPart {
ThemeDocument doc =
ThemeDocument.Factory.parse(getPackagePart().getInputStream(), DEFAULT_XML_OPTIONS);
_theme = doc.getTheme();
initialize();
}
@SuppressWarnings("WeakerAccess")
public void importTheme(XSLFTheme theme) {
_theme = theme.getXmlObject();
_schemeColors = theme._schemeColors;
}
private void initialize(){
CTBaseStyles elems = _theme.getThemeElements();
CTColorScheme scheme = elems.getClrScheme();
// The color scheme is responsible for defining a list of twelve colors.
_schemeColors = new HashMap<>(12);
for(XmlObject o : scheme.selectPath("*")){
CTColor c = (CTColor)o;
String name = c.getDomNode().getLocalName();
_schemeColors.put(name, c);
}
}
/**
* re-map colors
*
* @param cmap color map defined in the master slide referencing this theme
*/
void initColorMap(CTColorMapping cmap) {
_schemeColors.put("bg1", _schemeColors.get(cmap.getBg1().toString()));
_schemeColors.put("bg2", _schemeColors.get(cmap.getBg2().toString()));
_schemeColors.put("tx1", _schemeColors.get(cmap.getTx1().toString()));
_schemeColors.put("tx2", _schemeColors.get(cmap.getTx2().toString()));
}
/**
@ -119,7 +85,44 @@ public class XSLFTheme extends POIXMLDocumentPart {
*/
@Internal
public CTColor getCTColor(String name) {
return _schemeColors.get(name);
CTBaseStyles elems = _theme.getThemeElements();
CTColorScheme scheme = (elems == null) ? null : elems.getClrScheme();
return getMapColor(name, scheme);
}
private static CTColor getMapColor(String mapName, CTColorScheme scheme) {
if (mapName == null || scheme == null) {
return null;
}
switch (mapName) {
case "accent1":
return scheme.getAccent1();
case "accent2":
return scheme.getAccent2();
case "accent3":
return scheme.getAccent3();
case "accent4":
return scheme.getAccent4();
case "accent5":
return scheme.getAccent5();
case "accent6":
return scheme.getAccent6();
case "dk1":
return scheme.getDk1();
case "dk2":
return scheme.getDk2();
case "folHlink":
return scheme.getFolHlink();
case "hlink":
return scheme.getHlink();
case "lt1":
return scheme.getLt1();
case "lt2":
return scheme.getLt2();
default:
return null;
}
}
/**

View File

@ -40,7 +40,7 @@ public class TestXSLFColor {
CTSRgbColor c = xml.addNewSrgbClr();
c.setVal(new byte[]{(byte)0xFF, 0, 0});
XSLFColor color = new XSLFColor(xml, null, null);
XSLFColor color = new XSLFColor(xml, null, null, null);
assertEquals(-1, color.getAlpha());
c.addNewAlpha().setVal(50000);
@ -103,7 +103,7 @@ public class TestXSLFColor {
c.setSat2(100000);
c.setLum2(50000);
XSLFColor color = new XSLFColor(xml, null, null);
XSLFColor color = new XSLFColor(xml, null, null, null);
assertEquals(Color.BLUE, color.getColor());
}
@ -112,31 +112,32 @@ public class TestXSLFColor {
CTColor xml = CTColor.Factory.newInstance();
xml.addNewSrgbClr().setVal(new byte[]{ (byte)0xFF, (byte)0xFF, 0});
XSLFColor color = new XSLFColor(xml, null, null);
XSLFColor color = new XSLFColor(xml, null, null, null);
assertEquals(new Color(0xFF, 0xFF, 0), color.getColor());
}
@Test
public void testSchemeColor() throws IOException {
XMLSlideShow ppt = new XMLSlideShow();
XSLFTheme theme = ppt.createSlide().getTheme();
XSLFSheet slide = ppt.createSlide();
XSLFTheme theme = slide.getTheme();
CTColor xml = CTColor.Factory.newInstance();
xml.addNewSchemeClr().setVal(STSchemeColorVal.ACCENT_2);
XSLFColor color = new XSLFColor(xml, theme, null);
XSLFColor color = new XSLFColor(xml, theme, null, slide);
// accent2 is theme1.xml is <a:srgbClr val="C0504D"/>
assertEquals(Color.decode("0xC0504D"), color.getColor());
xml = CTColor.Factory.newInstance();
xml.addNewSchemeClr().setVal(STSchemeColorVal.LT_1);
color = new XSLFColor(xml, theme, null);
color = new XSLFColor(xml, theme, null, slide);
// <a:sysClr val="window" lastClr="FFFFFF"/>
assertEquals(Color.decode("0xFFFFFF"), color.getColor());
xml = CTColor.Factory.newInstance();
xml.addNewSchemeClr().setVal(STSchemeColorVal.DK_1);
color = new XSLFColor(xml, theme, null);
color = new XSLFColor(xml, theme, null, slide);
// <a:sysClr val="windowText" lastClr="000000"/>
assertEquals(Color.decode("0x000000"), color.getColor());
@ -147,7 +148,7 @@ public class TestXSLFColor {
public void testPresetColor() {
CTColor xml = CTColor.Factory.newInstance();
xml.addNewPrstClr().setVal(STPresetColorVal.AQUAMARINE);
XSLFColor color = new XSLFColor(xml, null, null);
XSLFColor color = new XSLFColor(xml, null, null, null);
assertEquals(new Color(127, 255, 212), color.getColor());
@ -162,7 +163,7 @@ public class TestXSLFColor {
} else {
xml.addNewSysClr().setVal(sysVal);
}
color = new XSLFColor(xml, null, null);
color = new XSLFColor(xml, null, null, null);
assertEquals(pc.color, color.getColor());
}
}
@ -172,13 +173,13 @@ public class TestXSLFColor {
CTColor xml = CTColor.Factory.newInstance();
CTSystemColor sys = xml.addNewSysClr();
sys.setVal(STSystemColorVal.CAPTION_TEXT);
XSLFColor color = new XSLFColor(xml, null, null);
XSLFColor color = new XSLFColor(xml, null, null, null);
assertEquals(Color.black, color.getColor());
xml = CTColor.Factory.newInstance();
sys = xml.addNewSysClr();
sys.setLastClr(new byte[]{(byte)0xFF, 0, 0});
color = new XSLFColor(xml, null, null);
color = new XSLFColor(xml, null, null, null);
assertEquals(Color.red, color.getColor());
}
}

View File

@ -41,7 +41,25 @@ import org.apache.poi.hslf.model.textproperties.TextPFException9;
import org.apache.poi.hslf.model.textproperties.TextProp;
import org.apache.poi.hslf.model.textproperties.TextPropCollection;
import org.apache.poi.hslf.model.textproperties.TextPropCollection.TextPropType;
import org.apache.poi.hslf.record.*;
import org.apache.poi.hslf.record.ColorSchemeAtom;
import org.apache.poi.hslf.record.EscherTextboxWrapper;
import org.apache.poi.hslf.record.InteractiveInfo;
import org.apache.poi.hslf.record.MasterTextPropAtom;
import org.apache.poi.hslf.record.OutlineTextRefAtom;
import org.apache.poi.hslf.record.PPDrawing;
import org.apache.poi.hslf.record.RecordContainer;
import org.apache.poi.hslf.record.RecordTypes;
import org.apache.poi.hslf.record.RoundTripHFPlaceholder12;
import org.apache.poi.hslf.record.SlideListWithText;
import org.apache.poi.hslf.record.SlidePersistAtom;
import org.apache.poi.hslf.record.StyleTextProp9Atom;
import org.apache.poi.hslf.record.StyleTextPropAtom;
import org.apache.poi.hslf.record.TextBytesAtom;
import org.apache.poi.hslf.record.TextCharsAtom;
import org.apache.poi.hslf.record.TextHeaderAtom;
import org.apache.poi.hslf.record.TextRulerAtom;
import org.apache.poi.hslf.record.TextSpecInfoAtom;
import org.apache.poi.hslf.record.TxInteractiveInfoAtom;
import org.apache.poi.sl.draw.DrawPaint;
import org.apache.poi.sl.usermodel.AutoNumberingScheme;
import org.apache.poi.sl.usermodel.PaintStyle;
@ -141,7 +159,7 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFShape,HSLFText
_byteAtom = tba;
_charAtom = tca;
this.parentList = parentList;
_paragraphStyle = new TextPropCollection(1, TextPropType.paragraph);
setParagraphStyle(new TextPropCollection(1, TextPropType.paragraph));
}
/* package */HSLFTextParagraph(HSLFTextParagraph other) {
@ -152,8 +170,8 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFShape,HSLFText
_sheet = other._sheet;
_ruler = other._ruler;
shapeId = other.shapeId;
_paragraphStyle = other._paragraphStyle;
parentList = other.parentList;
setParagraphStyle(other._paragraphStyle);
}
public void addTextRun(HSLFTextRun run) {