git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1872984 13f79535-47bb-0310-9956-ffa450edef68tags/REL_4_1_2
@@ -75,7 +75,7 @@ public class BitmapImageRenderer implements ImageRenderer { | |||
public void loadImage(byte[] data, String contentType) throws IOException { | |||
img = readImage(new ByteArrayInputStream(data), contentType); | |||
} | |||
/** | |||
* Read the image data via ImageIO and optionally try to workaround metadata errors. | |||
* The resulting image is of image type {@link BufferedImage#TYPE_INT_ARGB} | |||
@@ -117,7 +117,7 @@ public class BitmapImageRenderer implements ImageRenderer { | |||
} | |||
try { | |||
switch (mode) { | |||
case 0: | |||
reader.setInput(iis, false, true); | |||
@@ -146,7 +146,7 @@ public class BitmapImageRenderer implements ImageRenderer { | |||
reader.setInput(iis, false, true); | |||
int height = reader.getHeight(0); | |||
int width = reader.getWidth(0); | |||
Iterator<ImageTypeSpecifier> imageTypes = reader.getImageTypes(0); | |||
if (imageTypes.hasNext()) { | |||
ImageTypeSpecifier imageTypeSpecifier = imageTypes.next(); | |||
@@ -172,11 +172,11 @@ public class BitmapImageRenderer implements ImageRenderer { | |||
img = argbImg; | |||
} | |||
} | |||
} | |||
} | |||
break; | |||
} | |||
} | |||
} catch (IOException e) { | |||
if (mode < 2) { | |||
lastException = e; | |||
@@ -192,7 +192,7 @@ public class BitmapImageRenderer implements ImageRenderer { | |||
} finally { | |||
iis.close(); | |||
} | |||
// If you don't have an image at the end of all readers | |||
if (img == null) { | |||
if (lastException != null) { | |||
@@ -212,7 +212,7 @@ public class BitmapImageRenderer implements ImageRenderer { | |||
g.dispose(); | |||
return argbImg; | |||
} | |||
return img; | |||
} | |||
@@ -229,8 +229,8 @@ public class BitmapImageRenderer implements ImageRenderer { | |||
} | |||
return 0; | |||
} | |||
@Override | |||
public BufferedImage getImage() { | |||
return img; | |||
@@ -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); |
@@ -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 (off == -1) { | |||
off = 0; | |||
if (mod != -1) { | |||
hsl[hslPart] *= mod / 100_000d; | |||
} | |||
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; | |||
} | |||
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 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()]; | |||
} | |||
int i=0; | |||
for (Map.Entry<Float,Color> me : m.entrySet()) { | |||
fractions[i] = me.getKey(); | |||
colors[i] = me.getValue(); | |||
i++; | |||
} | |||
return init.apply(toArray(m.keySet()), m.values().toArray(new Color[0])); | |||
} | |||
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; | |||
} | |||
/** |
@@ -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,8 +87,8 @@ 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,8 +97,12 @@ public interface PaintStyle { | |||
float[] getGradientFractions(); | |||
boolean isRotatedWithShape(); | |||
GradientType getGradientType(); | |||
} | |||
default Insets2D getFillToInsets() { | |||
return null; | |||
} | |||
} | |||
interface TexturePaint extends PaintStyle { | |||
/** | |||
* @return the raw image stream | |||
@@ -109,7 +113,7 @@ public interface PaintStyle { | |||
* @return the content type of the image data | |||
*/ | |||
String getContentType(); | |||
/** | |||
* @return the alpha mask in percents [0..100000] | |||
*/ | |||
@@ -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; | |||
} | |||
} | |||
} |
@@ -48,7 +48,7 @@ public class XSLFBackground extends XSLFSimpleShape | |||
/** | |||
* background does not have a associated transform, therefore we return null | |||
* | |||
* | |||
* @param create ignored | |||
* | |||
* @return null | |||
@@ -57,7 +57,7 @@ public class XSLFBackground extends XSLFSimpleShape | |||
protected CTTransform2D getXfrm(boolean create) { | |||
return null; | |||
} | |||
@Override | |||
public void setPlaceholder(Placeholder placeholder) { | |||
// extending XSLFSimpleShape is a bit unlucky ... | |||
@@ -74,7 +74,7 @@ public class XSLFBackground extends XSLFSimpleShape | |||
} | |||
return bg.getBgPr(); | |||
} | |||
public void setFillColor(Color color) { | |||
CTBackgroundProperties bgPr = getBgPr(true); | |||
@@ -105,8 +105,8 @@ 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); | |||
} | |||
} |
@@ -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,116 +79,87 @@ public class XSLFColor { | |||
return DrawPaint.applyColorTransform(getColorStyle()); | |||
} | |||
@SuppressWarnings("WeakerAccess") | |||
public ColorStyle getColorStyle() { | |||
return new AbstractColorStyle() { | |||
@Override | |||
public Color getColor() { | |||
return _color; | |||
} | |||
@Override | |||
public int getAlpha() { | |||
return getRawValue("alpha"); | |||
} | |||
@Override | |||
public int getHueOff() { | |||
return getRawValue("hueOff"); | |||
} | |||
@Override | |||
public int getHueMod() { | |||
return getRawValue("hueMod"); | |||
} | |||
return new XSLFColorStyle(_xmlObject, _color, _phClr); | |||
} | |||
@Override | |||
public int getSatOff() { | |||
return getRawValue("satOff"); | |||
} | |||
private Color toColor(CTHslColor hsl) { | |||
return DrawPaint.HSL2RGB( | |||
hsl.getHue2() / 60000d, | |||
hsl.getSat2() / 1000d, | |||
hsl.getLum2() / 1000d, | |||
1d); | |||
} | |||
@Override | |||
public int getSatMod() { | |||
return getRawValue("satMod"); | |||
} | |||
private Color toColor(CTPresetColor prst) { | |||
String colorName = prst.getVal().toString(); | |||
PresetColor pc = PresetColor.valueOfOoxmlId(colorName); | |||
return (pc != null) ? pc.color : null; | |||
} | |||
@Override | |||
public int getLumOff() { | |||
return getRawValue("lumOff"); | |||
} | |||
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(_sheet.mapSchemeColor(colorRef)); | |||
return (ctColor != null) ? toColor(ctColor, null) : null; | |||
} | |||
@Override | |||
public int getLumMod() { | |||
return getRawValue("lumMod"); | |||
} | |||
private Color toColor(CTScRgbColor scrgb) { | |||
// color in percentage is in linear RGB color space, i.e. needs to be gamma corrected for AWT color | |||
return new Color(DrawPaint.lin2srgb(scrgb.getR()), DrawPaint.lin2srgb(scrgb.getG()), DrawPaint.lin2srgb(scrgb.getB())); | |||
} | |||
@Override | |||
public int getShade() { | |||
return getRawValue("shade"); | |||
} | |||
private Color toColor(CTSRgbColor srgb) { | |||
// color in sRGB color space, i.e. same as AWT Color | |||
byte[] val = srgb.getVal(); | |||
return new Color(0xFF & val[0], 0xFF & val[1], 0xFF & val[2]); | |||
} | |||
@Override | |||
public int getTint() { | |||
return getRawValue("tint"); | |||
} | |||
}; | |||
private Color toColor(CTSystemColor sys) { | |||
if (sys.isSetLastClr()) { | |||
byte[] val = sys.getLastClr(); | |||
return new Color(0xFF & val[0], 0xFF & val[1], 0xFF & val[2]); | |||
} else { | |||
String colorName = sys.getVal().toString(); | |||
PresetColor pc = PresetColor.valueOfOoxmlId(colorName); | |||
return (pc != null && pc.color != null) ? pc.color : Color.black; | |||
} | |||
} | |||
private Color toColor(XmlObject obj, XSLFTheme theme) { | |||
Color color = null; | |||
for (XmlObject ch : obj.selectPath("*")) { | |||
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) { | |||
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); | |||
color = toColor((CTHslColor)ch); | |||
} else if (ch instanceof CTPresetColor) { | |||
CTPresetColor prst = (CTPresetColor)ch; | |||
String colorName = prst.getVal().toString(); | |||
PresetColor pc = PresetColor.valueOfOoxmlId(colorName); | |||
if (pc != null) { | |||
color = pc.color; | |||
} | |||
color = toColor((CTPresetColor)ch); | |||
} else if (ch instanceof CTSchemeColor) { | |||
CTSchemeColor schemeColor = (CTSchemeColor)ch; | |||
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); | |||
} | |||
color = toColor((CTSchemeColor)ch, theme); | |||
} else if (ch instanceof CTScRgbColor) { | |||
// 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())); | |||
color = toColor((CTScRgbColor)ch); | |||
} else if (ch instanceof CTSRgbColor) { | |||
// 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]); | |||
color = toColor((CTSRgbColor)ch); | |||
} else if (ch instanceof CTSystemColor) { | |||
CTSystemColor sys = (CTSystemColor)ch; | |||
if(sys.isSetLastClr()) { | |||
byte[] val = sys.getLastClr(); | |||
color = 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; | |||
} | |||
} | |||
color = toColor((CTSystemColor)ch); | |||
} else if (!(ch instanceof CTFontReference)) { | |||
throw new IllegalArgumentException("Unexpected color choice: " + ch.getClass()); | |||
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"); | |||
} | |||
} | |||
} |
@@ -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; | |||
} | |||
} |
@@ -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); | |||
} | |||
} |
@@ -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; | |||
@@ -65,12 +64,12 @@ import org.openxmlformats.schemas.presentationml.x2006.main.NotesMasterDocument; | |||
NotesMasterDocument.Factory.parse(getPackagePart().getInputStream(), DEFAULT_XML_OPTIONS); | |||
_slide = doc.getNotesMaster(); | |||
} | |||
private static CTNotesMaster prototype() { | |||
InputStream is = XSLFNotesMaster.class.getResourceAsStream("notesMaster.xml"); | |||
if (is == null) { | |||
throw new POIXMLException("Missing resource 'notesMaster.xml'"); | |||
} | |||
} | |||
try { | |||
try { | |||
@@ -78,12 +77,12 @@ import org.openxmlformats.schemas.presentationml.x2006.main.NotesMasterDocument; | |||
return doc.getNotesMaster(); | |||
} finally { | |||
is.close(); | |||
} | |||
} | |||
} catch (Exception e) { | |||
throw new POIXMLException("Can't initialize NotesMaster", e); | |||
} | |||
} | |||
@Override | |||
public CTNotesMaster getXmlObject() { | |||
return _slide; | |||
@@ -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; | |||
} | |||
} |
@@ -61,11 +61,11 @@ public class XSLFShadow extends XSLFShape implements Shadow<XSLFShape,XSLFTextPa | |||
*/ | |||
public double getDistance(){ | |||
CTOuterShadowEffect ct = (CTOuterShadowEffect)getXmlObject(); | |||
return ct.isSetDist() ? Units.toPoints(ct.getDist()) : 0; | |||
return ct.isSetDist() ? Units.toPoints(ct.getDist()) : 0; | |||
} | |||
/** | |||
* | |||
* | |||
* @return the direction to offset the shadow in angles | |||
*/ | |||
public double getAngle(){ | |||
@@ -74,9 +74,9 @@ public class XSLFShadow extends XSLFShape implements Shadow<XSLFShape,XSLFTextPa | |||
} | |||
/** | |||
* | |||
* | |||
* @return the blur radius of the shadow | |||
* TODO: figure out how to make sense of this property when rendering shadows | |||
* TODO: figure out how to make sense of this property when rendering shadows | |||
*/ | |||
public double getBlur(){ | |||
CTOuterShadowEffect ct = (CTOuterShadowEffect)getXmlObject(); | |||
@@ -84,7 +84,7 @@ public class XSLFShadow extends XSLFShape implements Shadow<XSLFShape,XSLFTextPa | |||
} | |||
/** | |||
* @return the color of this shadow. | |||
* @return the color of this shadow. | |||
* Depending whether the parent shape is filled or stroked, this color is used to fill or stroke this shadow | |||
*/ | |||
public Color getFillColor() { | |||
@@ -98,9 +98,9 @@ public class XSLFShadow extends XSLFShape implements Shadow<XSLFShape,XSLFTextPa | |||
XSLFTheme theme = getSheet().getTheme(); | |||
CTOuterShadowEffect ct = (CTOuterShadowEffect)getXmlObject(); | |||
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()); | |||
} | |||
} |
@@ -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()); | |||
} | |||
@@ -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(); | |||
} | |||
} |
@@ -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 | |||
@@ -130,7 +104,7 @@ public abstract class XSLFSimpleShape extends XSLFShape | |||
} | |||
}; | |||
fetchShapeProperty(fetcher); | |||
CTTransform2D xfrm = fetcher.getValue(); | |||
if (!create || xfrm != null) { | |||
return xfrm; | |||
@@ -286,12 +260,12 @@ public abstract class XSLFSimpleShape extends XSLFShape | |||
ln.unsetNoFill(); | |||
} | |||
if (color == null) { | |||
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); | |||
} | |||
} | |||
@@ -325,7 +299,7 @@ public abstract class XSLFSimpleShape extends XSLFShape | |||
setValue(null); | |||
return true; | |||
} | |||
PackagePart pp = shape.getSheet().getPackagePart(); | |||
PaintStyle paint = selectPaint(fp, null, pp, theme, hasPlaceholder); | |||
if (paint != null) { | |||
@@ -343,12 +317,12 @@ public abstract class XSLFSimpleShape extends XSLFShape | |||
paint = getThemePaint(style, pp); | |||
} | |||
} | |||
if (paint != null) { | |||
setValue(paint); | |||
return true; | |||
} | |||
return false; | |||
} | |||
@@ -384,7 +358,7 @@ public abstract class XSLFSimpleShape extends XSLFShape | |||
if (lnPr == null) { | |||
return; | |||
} | |||
if (width == 0.) { | |||
if (lnPr.isSetW()) { | |||
lnPr.unsetW(); | |||
@@ -592,7 +566,7 @@ public abstract class XSLFSimpleShape extends XSLFShape | |||
if (ln == null) { | |||
return; | |||
} | |||
if (cap == null) { | |||
if (ln.isSetCap()) { | |||
ln.unsetCap(); | |||
@@ -641,7 +615,7 @@ public abstract class XSLFSimpleShape extends XSLFShape | |||
if (fp.isSetSolidFill()) { | |||
fp.unsetSolidFill(); | |||
} | |||
if (fp.isSetGradFill()) { | |||
fp.unsetGradFill(); | |||
} | |||
@@ -649,11 +623,11 @@ public abstract class XSLFSimpleShape extends XSLFShape | |||
if (fp.isSetPattFill()) { | |||
fp.unsetGradFill(); | |||
} | |||
if (fp.isSetBlipFill()) { | |||
fp.unsetBlipFill(); | |||
} | |||
if (!fp.isSetNoFill()) { | |||
fp.addNewNoFill(); | |||
} | |||
@@ -663,8 +637,8 @@ 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); | |||
} | |||
} | |||
@@ -720,11 +694,11 @@ public abstract class XSLFSimpleShape extends XSLFShape | |||
@Override | |||
public CustomGeometry getGeometry() { | |||
XSLFGeometryProperties gp = XSLFPropertiesDelegate.getGeometryDelegate(getShapeProperties()); | |||
if (gp == null) { | |||
return null; | |||
} | |||
CustomGeometry geom; | |||
PresetGeometries dict = PresetGeometries.getInstance(); | |||
if(gp.isSetPrstGeom()){ | |||
@@ -798,7 +772,7 @@ public abstract class XSLFSimpleShape extends XSLFShape | |||
/** | |||
* Specifies the line end decoration, such as a triangle or arrowhead. | |||
* | |||
* | |||
* @param style the line end docoration style | |||
*/ | |||
@SuppressWarnings("WeakerAccess") | |||
@@ -832,8 +806,8 @@ public abstract class XSLFSimpleShape extends XSLFShape | |||
/** | |||
* specifies decoration width of the head of a line. | |||
* | |||
* @param style the decoration width | |||
* | |||
* @param style the decoration width | |||
*/ | |||
@SuppressWarnings("WeakerAccess") | |||
public void setLineHeadWidth(DecorationSize style) { | |||
@@ -873,7 +847,7 @@ public abstract class XSLFSimpleShape extends XSLFShape | |||
if (ln == null) { | |||
return; | |||
} | |||
CTLineEndProperties lnEnd = ln.isSetHeadEnd() ? ln.getHeadEnd() : ln.addNewHeadEnd(); | |||
if (style == null) { | |||
if (lnEnd.isSetLen()) { | |||
@@ -890,12 +864,12 @@ public abstract class XSLFSimpleShape extends XSLFShape | |||
@SuppressWarnings("WeakerAccess") | |||
public DecorationSize getLineHeadLength() { | |||
CTLineProperties ln = getLn(this, false); | |||
DecorationSize ds = DecorationSize.MEDIUM; | |||
if (ln != null && ln.isSetHeadEnd() && ln.getHeadEnd().isSetLen()) { | |||
ds = DecorationSize.fromOoxmlId(ln.getHeadEnd().getLen().intValue()); | |||
} | |||
return ds; | |||
return ds; | |||
} | |||
/** | |||
@@ -924,7 +898,7 @@ public abstract class XSLFSimpleShape extends XSLFShape | |||
@SuppressWarnings("WeakerAccess") | |||
public DecorationShape getLineTailDecoration() { | |||
CTLineProperties ln = getLn(this, false); | |||
DecorationShape ds = DecorationShape.NONE; | |||
if (ln != null && ln.isSetTailEnd() && ln.getTailEnd().isSetType()) { | |||
ds = DecorationShape.fromOoxmlId(ln.getTailEnd().getType().intValue()); | |||
@@ -941,7 +915,7 @@ public abstract class XSLFSimpleShape extends XSLFShape | |||
if (ln == null) { | |||
return; | |||
} | |||
CTLineEndProperties lnEnd = ln.isSetTailEnd() ? ln.getTailEnd() : ln.addNewTailEnd(); | |||
if (style == null) { | |||
if (lnEnd.isSetW()) { | |||
@@ -974,7 +948,7 @@ public abstract class XSLFSimpleShape extends XSLFShape | |||
if (ln == null) { | |||
return; | |||
} | |||
CTLineEndProperties lnEnd = ln.isSetTailEnd() ? ln.getTailEnd() : ln.addNewTailEnd(); | |||
if (style == null) { | |||
if (lnEnd.isSetLen()) { | |||
@@ -991,18 +965,18 @@ public abstract class XSLFSimpleShape extends XSLFShape | |||
@SuppressWarnings("WeakerAccess") | |||
public DecorationSize getLineTailLength() { | |||
CTLineProperties ln = getLn(this, false); | |||
DecorationSize ds = DecorationSize.MEDIUM; | |||
if (ln != null && ln.isSetTailEnd() && ln.getTailEnd().isSetLen()) { | |||
ds = DecorationSize.fromOoxmlId(ln.getTailEnd().getLen().intValue()); | |||
} | |||
return ds; | |||
return ds; | |||
} | |||
@Override | |||
public Guide getAdjustValue(String name) { | |||
XSLFGeometryProperties gp = XSLFPropertiesDelegate.getGeometryDelegate(getShapeProperties()); | |||
if (gp != null && gp.isSetPrstGeom() && gp.getPrstGeom().isSetAvLst()) { | |||
//noinspection deprecation | |||
for (CTGeomGuide g : gp.getPrstGeom().getAvLst().getGdArray()) { | |||
@@ -1098,7 +1072,7 @@ public abstract class XSLFSimpleShape extends XSLFShape | |||
setLineColor(null); | |||
return; | |||
} | |||
// TODO: handle PaintStyle | |||
for (Object st : styles) { | |||
if (st instanceof Number) { | |||
@@ -1114,7 +1088,7 @@ public abstract class XSLFSimpleShape extends XSLFShape | |||
} | |||
} | |||
} | |||
@Override | |||
public XSLFHyperlink getHyperlink() { | |||
CTNonVisualDrawingProps cNvPr = getCNvPr(); | |||
@@ -1123,7 +1097,7 @@ public abstract class XSLFSimpleShape extends XSLFShape | |||
} | |||
return new XSLFHyperlink(cNvPr.getHlinkClick(), getSheet()); | |||
} | |||
@Override | |||
public XSLFHyperlink createHyperlink() { | |||
XSLFHyperlink hl = getHyperlink(); | |||
@@ -1140,7 +1114,7 @@ public abstract class XSLFSimpleShape extends XSLFShape | |||
LOG.log(POILogger.WARN, shape.getClass() +" doesn't have line properties"); | |||
return null; | |||
} | |||
CTShapeProperties spr = (CTShapeProperties)pr; | |||
return (spr.isSetLn() || !create) ? spr.getLn() : spr.addNewLn(); | |||
} |
@@ -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; | |||
@@ -283,7 +283,7 @@ implements Slide<XSLFShape,XSLFTextParagraph> { | |||
public boolean getFollowMasterObjects() { | |||
return getFollowMasterGraphics(); | |||
} | |||
@Override | |||
public void setFollowMasterObjects(boolean follow) { | |||
setFollowMasterGraphics(follow); | |||
@@ -328,7 +328,7 @@ implements Slide<XSLFShape,XSLFTextParagraph> { | |||
public boolean getFollowMasterBackground() { | |||
return false; | |||
} | |||
@Override | |||
@NotImplemented | |||
public void setFollowMasterBackground(boolean follow) { | |||
@@ -340,7 +340,7 @@ implements Slide<XSLFShape,XSLFTextParagraph> { | |||
public boolean getFollowMasterColourScheme() { | |||
return false; | |||
} | |||
@Override | |||
@NotImplemented | |||
public void setFollowMasterColourScheme(boolean follow) { | |||
@@ -378,7 +378,7 @@ implements Slide<XSLFShape,XSLFTextParagraph> { | |||
return false; | |||
} | |||
@Override | |||
public void setHidden(boolean hidden) { | |||
CTSlide sld = getXmlObject(); | |||
@@ -391,7 +391,7 @@ implements Slide<XSLFShape,XSLFTextParagraph> { | |||
} | |||
} | |||
} | |||
@Override | |||
public boolean isHidden() { | |||
CTSlide sld = getXmlObject(); | |||
@@ -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); | |||
} | |||
} |
@@ -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); | |||
} | |||
} |
@@ -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; | |||
@@ -66,7 +65,7 @@ import org.openxmlformats.schemas.presentationml.x2006.main.SldMasterDocument; | |||
SldMasterDocument.Factory.parse(getPackagePart().getInputStream(), DEFAULT_XML_OPTIONS); | |||
_slide = doc.getSldMaster(); | |||
} | |||
@Override | |||
public CTSlideMaster getXmlObject() { | |||
return _slide; | |||
@@ -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; | |||
} | |||
} |
@@ -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()); | |||
} | |||
@@ -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; | |||
} |
@@ -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); |
@@ -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), |
@@ -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())); | |||
} | |||
/** | |||
@@ -118,8 +84,45 @@ public class XSLFTheme extends POIXMLDocumentPart { | |||
* @return a theme color or <code>null</code> if not found | |||
*/ | |||
@Internal | |||
public CTColor getCTColor(String name){ | |||
return _schemeColors.get(name); | |||
public CTColor getCTColor(String 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; | |||
} | |||
} | |||
/** |
@@ -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()); | |||
} | |||
} |
@@ -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) { |