]> source.dussan.org Git - poi.git/commitdiff
#64088 - SlideShow rendering fixes
authorAndreas Beeker <kiwiwings@apache.org>
Sun, 19 Jan 2020 20:44:36 +0000 (20:44 +0000)
committerAndreas Beeker <kiwiwings@apache.org>
Sun, 19 Jan 2020 20:44:36 +0000 (20:44 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1872984 13f79535-47bb-0310-9956-ffa450edef68

22 files changed:
src/java/org/apache/poi/sl/draw/BitmapImageRenderer.java
src/java/org/apache/poi/sl/draw/DrawPaint.java
src/java/org/apache/poi/sl/usermodel/PaintStyle.java
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFBackground.java
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFColor.java
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFGradientPaint.java
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFNotes.java
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFNotesMaster.java
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFShadow.java
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFShape.java
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSheet.java
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSimpleShape.java
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSlide.java
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSlideLayout.java
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSlideMaster.java
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTableCell.java
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextParagraph.java
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextRun.java
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTexturePaint.java
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTheme.java
src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFColor.java
src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTextParagraph.java

index 3f6c8868594ebf1dace3d1b6de2a75317de844e0..7b7fd7aa212c9c9bef76b04b67212b32d81515d4 100644 (file)
@@ -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);
index 60a861cc49a38769d30da4a6c1bea1fba93a0536..d8a11a956e54166d0945618405f858acd20b145a 100644 (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 (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;
     }
 
     /**
index 92371b68c53febdf95a5720ecd23f78a6f441f3c..21f0824a2f88db85b71ef11ec77af0a36b781614 100644 (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,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;
+        }
+
     }
 }
index dbc623b14191104354c6a247bd9bc72a36204329..add51e6566e8b84a37a8bb7c6fce3f36306a8c26 100644 (file)
@@ -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);
         }
     }
index 95fc4a138665525d505f474bd5c5bd0497319455..7a2e6e2b975ff5026eb55fe0ea5b9994467b5f69 100644 (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,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");
+        }
+    }
 }
index a39ffd5bcf0ef89502020c3f70fba22567875e6c..f86d2e9035b6814edbbc9944724d19c29e563fd5 100644 (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;
+    }
 }
index 72d19e7aee7f2b868a93df5f2d0f851bf822bf32..19b42c119f572314026566354c243ed9f6a586f1 100644 (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);
+    }
 }
index 833ea8f608cc2ff1b7641c61caa735c2c5df5ef7..6ebe1855312136283e32090551053bee02389a19 100644 (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;
 
@@ -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;
     }
 }
\ No newline at end of file
index 619b10f216e27312e0ba677d2e23a41ac5974fb4..9ec4e3e6bc1b4022e07f731b9f191a12ad38c905 100644 (file)
@@ -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());
     }
 }
\ No newline at end of file
index fa8a8ff3db5bf78ec543b02a1a429f9b2d88cab0..7d80fbe3b95705235aa079d408093b7d61002365 100644 (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());
     }
 
index 97c490d82ee51d50f782a8e0c21330768d22cf78..d78a35bee2ac8531fdc17cecebbf75d53771826d 100644 (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();
+    }
 }
index 4d98ecb2eb23728907e3e0f19721ca551a24d548..e77820184e43a3beb8b2f34920dd3eb12dee6a79 100644 (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
@@ -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();
     }
index 33baa4c173d2e65db39ccb1ae04dafede9ed2b1e..32456a3aa2c8f0444ef5260338e48bf9f02e4e6b 100644 (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;
@@ -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);
+    }
 }
index 569c6c248917e367ff873e97f497037ad06fe60c..17f66bec0ad0de23c73e24b37d22400cd9dea64f 100644 (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);
+    }
 }
\ No newline at end of file
index 558e6b5cdad091f3c14aaf99b25019de1bd6064b..7a20d04d1d120ea9acddb435d13f545ed208d82e 100644 (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;
@@ -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;
     }
 }
index 011914f16edc99404f573bdb818daf287d3a7ea1..76f5a0d92b3109238f411bea469d22d77ad366c7 100644 (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());
         }
 
index f07135213ad54dd37f9d9548deff876d2e2c840f..17a67794edc86711e071e4d831aed8ddc7128da7 100644 (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;
                 }
index 3305b1a26da9c605420bdef6d96a55f26159606e..677ebc91edff9dedf910916c0394ec7ff6ca1053 100644 (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);
index bc3ac3227c7a838315f5fe4d64ca7f20c40de6be..2a2c8edf8bd8f7c1a0f97246c887dda104599531 100644 (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),
index 929839b96dac70f1d427fc836045c3055109734f..8744b8069075dfe290d20f83e166f4aea7354d35 100644 (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()));
     }
 
     /**
@@ -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;
+        }
     }
 
     /**
index a862c16b44c8b79402a1dbd58fe961cdcbfb9886..cfadb58cc04f212c932088ba07586089ce08e5ce 100644 (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());
     }
 }
\ No newline at end of file
index 7923ced34a0fe8b5e5cdd9f5a74d1b4b06254716..ba9d1495bcd5569858e6ba6b970a3ccdd32613f1 100644 (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) {