]> source.dussan.org Git - poi.git/commitdiff
#58130 HSSF CF Color Scale color support
authorNick Burch <nick@apache.org>
Mon, 20 Jul 2015 00:47:27 +0000 (00:47 +0000)
committerNick Burch <nick@apache.org>
Mon, 20 Jul 2015 00:47:27 +0000 (00:47 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1691865 13f79535-47bb-0310-9956-ffa450edef68

src/java/org/apache/poi/hssf/record/common/ExtendedColor.java
src/java/org/apache/poi/hssf/usermodel/HSSFColorScaleFormatting.java
src/java/org/apache/poi/hssf/usermodel/HSSFExtendedColor.java [new file with mode: 0644]
src/java/org/apache/poi/hssf/usermodel/HSSFIconMultiStateFormatting.java
src/testcases/org/apache/poi/hssf/usermodel/TestHSSFConditionalFormatting.java
src/testcases/org/apache/poi/ss/usermodel/BaseTestConditionalFormatting.java

index 9aff0e21c15d251cdd448cacc6d1ae11f35ea619..b0719e19a8aea159caebf840d078476b0d7006c6 100644 (file)
@@ -37,21 +37,49 @@ public final class ExtendedColor {
     public static final int TYPE_THEMED = 3;
     public static final int TYPE_UNSET = 4;
     
-    private int type; 
-    // TODO Decode
-    private byte[] value;
+    public static final int THEME_DARK_1  = 0;
+    public static final int THEME_LIGHT_1 = 1;
+    public static final int THEME_DARK_2  = 2;
+    public static final int THEME_LIGHT_2 = 3;
+    public static final int THEME_ACCENT_1 = 4;
+    public static final int THEME_ACCENT_2 = 5;
+    public static final int THEME_ACCENT_3 = 6;
+    public static final int THEME_ACCENT_4 = 7;
+    public static final int THEME_ACCENT_5 = 8;
+    public static final int THEME_ACCENT_6 = 9;
+    public static final int THEME_HYPERLINK = 10;
+    // This one is SheetEx only, not allowed in CFs
+    public static final int THEME_FOLLOWED_HYPERLINK = 11;
+    
+    private int type;
+    
+    // Type = Indexed
+    private int colorIndex;
+    // Type = RGB
+    private byte[] rgba;
+    // Type = Theme
+    private int themeIndex;
+    
     private double tint;
     
     public ExtendedColor() {
         this.type = TYPE_INDEXED;
-        this.value = new byte[4];
+        this.colorIndex = 0;
         this.tint = 0d;
     }
     public ExtendedColor(LittleEndianInput in) {
         type = in.readInt();
-        // TODO Decode color
-        value = new byte[4];
-        in.readFully(value);
+        if (type == TYPE_INDEXED) {
+            colorIndex = in.readInt();
+        } else if (type == TYPE_RGB) {
+            rgba = new byte[4];
+            in.readFully(rgba);
+        } else if (type == TYPE_THEMED) {
+            themeIndex = in.readInt();
+        } else {
+            // Ignored
+            in.readInt();
+        }
         tint = in.readDouble();
     }
 
@@ -61,9 +89,36 @@ public final class ExtendedColor {
     public void setType(int type) {
         this.type = type;
     }
+
+    /**
+     * @return Palette color index, if type is {@link #TYPE_INDEXED}
+     */
+    public int getColorIndex() {
+        return colorIndex;
+    }
+    public void setColorIndex(int colorIndex) {
+        this.colorIndex = colorIndex;
+    }
     
-    // TODO Return the color details
+    /**
+     * @return Red Green Blue Alpha, if type is {@link #TYPE_RGB}
+     */
+    public byte[] getRGBA() {
+        return rgba;
+    }
+    public void setRGBA(byte[] rgba) {
+        this.rgba = rgba;
+    }
     
+    /**
+     * @return Theme color type index, eg {@link #THEME_DARK_1}, if type is {@link #TYPE_THEMED}
+     */
+    public int getThemeIndex() {
+        return themeIndex;
+    }
+    public void setThemeIndex(int themeIndex) {
+        this.themeIndex = themeIndex;
+    }
     /**
      * @return Tint and Shade value, between -1 and +1
      */
@@ -85,7 +140,9 @@ public final class ExtendedColor {
         buffer.append("    [Extended Color]\n");
         buffer.append("          .type  = ").append(type).append("\n");
         buffer.append("          .tint  = ").append(tint).append("\n");
-        buffer.append("          .color = ").append(HexDump.toHex(value)).append("\n");
+        buffer.append("          .c_idx = ").append(colorIndex).append("\n");
+        buffer.append("          .rgba  = ").append(HexDump.toHex(rgba)).append("\n");
+        buffer.append("          .t_idx = ").append(themeIndex).append("\n");
         buffer.append("    [/Extended Color]\n");
         return buffer.toString();
     }
@@ -94,8 +151,14 @@ public final class ExtendedColor {
         ExtendedColor exc = new ExtendedColor();
         exc.type = type;
         exc.tint = tint;
-        exc.value = new byte[value.length];
-        System.arraycopy(value, 0, exc.value, 0, value.length);
+        if (type == TYPE_INDEXED) {
+            exc.colorIndex = colorIndex;
+        } else if (type == TYPE_RGB) {
+            exc.rgba = new byte[4];
+            System.arraycopy(rgba, 0, exc.rgba, 0, 4);
+        } else if (type == TYPE_THEMED) {
+            exc.themeIndex = themeIndex;
+        }
         return exc;
     }
     
@@ -105,7 +168,15 @@ public final class ExtendedColor {
 
     public void serialize(LittleEndianOutput out) {
         out.writeInt(type);
-        out.write(value);
+        if (type == TYPE_INDEXED) {
+            out.writeInt(colorIndex);
+        } else if (type == TYPE_RGB) {
+            out.write(rgba);
+        } else if (type == TYPE_THEMED) {
+            out.writeInt(themeIndex);
+        } else {
+            out.writeInt(0);
+        }
         out.writeDouble(tint);
     }
 }
\ No newline at end of file
index 3d4613f98336c140339c9640485925ace61b284e..36c5a53e0c4057df6ad337e6f84d0697c297beb5 100644 (file)
@@ -21,6 +21,7 @@ import org.apache.poi.hssf.record.CFRule12Record;
 import org.apache.poi.hssf.record.cf.ColorGradientFormatting;
 import org.apache.poi.hssf.record.cf.ColorGradientThreshold;
 import org.apache.poi.hssf.record.cf.Threshold;
+import org.apache.poi.hssf.record.common.ExtendedColor;
 import org.apache.poi.ss.usermodel.Color;
 import org.apache.poi.ss.usermodel.ConditionalFormattingThreshold;
 
@@ -46,11 +47,20 @@ public final class HSSFColorScaleFormatting implements org.apache.poi.ss.usermod
         colorFormatting.setNumControlPoints(num);
     }
 
-    public Color[] getColors() {
-        return null; // TODO
+    public HSSFExtendedColor[] getColors() {
+        ExtendedColor[] colors = colorFormatting.getColors();
+        HSSFExtendedColor[] hcolors = new HSSFExtendedColor[colors.length];
+        for (int i=0; i<colors.length; i++) {
+            hcolors[i] = new HSSFExtendedColor(colors[i]);
+        }
+        return hcolors;
     }
     public void setColors(Color[] colors) {
-        // TODO
+        ExtendedColor[] cr = new ExtendedColor[colors.length];
+        for (int i=0; i<colors.length; i++) {
+            cr[i] = ((HSSFExtendedColor)colors[i]).getExtendedColor();
+        }
+        colorFormatting.setColors(cr);
     }
 
     public HSSFConditionalFormattingThreshold[] getThresholds() {
diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFExtendedColor.java b/src/java/org/apache/poi/hssf/usermodel/HSSFExtendedColor.java
new file mode 100644 (file)
index 0000000..7806fb5
--- /dev/null
@@ -0,0 +1,108 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+==================================================================== */
+
+package org.apache.poi.hssf.usermodel;
+
+import static org.apache.poi.hssf.record.common.ExtendedColor.TYPE_AUTO;
+import static org.apache.poi.hssf.record.common.ExtendedColor.TYPE_INDEXED;
+import static org.apache.poi.hssf.record.common.ExtendedColor.TYPE_RGB;
+import static org.apache.poi.hssf.record.common.ExtendedColor.TYPE_THEMED;
+
+import org.apache.poi.ss.usermodel.ExtendedColor;
+
+/**
+ * The HSSF file format normally stores Color information in the
+ *  Palette (see PaletteRecord), but for a few cases (eg Conditional
+ *  Formatting, Sheet Extensions), this XSSF-style color record 
+ *  can be used.
+ */
+public class HSSFExtendedColor extends ExtendedColor {
+    private org.apache.poi.hssf.record.common.ExtendedColor color;
+    
+    public HSSFExtendedColor(org.apache.poi.hssf.record.common.ExtendedColor color) {
+        this.color = color;
+    }
+    
+    protected org.apache.poi.hssf.record.common.ExtendedColor getExtendedColor() {
+        return color;
+    }
+
+    public boolean isAuto() {
+        return color.getType() == TYPE_AUTO;
+    }
+    public boolean isIndexed() {
+        return color.getType() == TYPE_INDEXED;
+    }
+    public boolean isRGB() {
+        return color.getType() == TYPE_RGB;
+    }
+    public boolean isThemed() {
+        return color.getType() == TYPE_THEMED;
+    }
+
+    public short getIndex() {
+        return (short)color.getColorIndex();
+    }
+    public int getTheme() {
+        return color.getThemeIndex();
+    }
+
+    public byte[] getRGB() {
+        // Trim trailing A
+        byte[] rgb = new byte[3];
+        byte[] rgba = color.getRGBA();
+        if (rgba == null) return null;
+        System.arraycopy(rgba, 0, rgb, 0, 3);
+        return rgb;
+    }
+    public byte[] getARGB() {
+        // Swap from RGBA to ARGB
+        byte[] argb = new byte[4];
+        byte[] rgba = color.getRGBA();
+        if (rgba == null) return null;
+        System.arraycopy(rgba, 0, argb, 1, 3);
+        argb[0] = rgba[3];
+        return argb;
+    }
+
+    protected byte[] getStoredRBG() {
+        return getARGB();
+    }
+
+    public void setRGB(byte[] rgb) {
+        if (rgb.length == 3) {
+            byte[] rgba = new byte[4];
+            System.arraycopy(rgb, 0, rgba, 0, 3);
+            rgba[3] = -1;
+        } else {
+            // Shuffle from ARGB to RGBA
+            byte a = rgb[0];
+            rgb[0] = rgb[1];
+            rgb[1] = rgb[2];
+            rgb[2] = rgb[3];
+            rgb[3] = a;
+            color.setRGBA(rgb);
+        }
+    }
+
+    public double getTint() {
+        return color.getTint();
+    }
+    public void setTint(double tint) {
+        color.setTint(tint);
+    }
+}
index e93d5c918f27a7afb5c0e35cff41471803fa375a..cabfad2f807d7994b5ee8bb16c2fc5ad24de0807 100644 (file)
@@ -19,6 +19,7 @@ package org.apache.poi.hssf.usermodel;
 
 import org.apache.poi.hssf.record.CFRule12Record;
 import org.apache.poi.hssf.record.cf.IconMultiStateFormatting;
+import org.apache.poi.hssf.record.cf.IconMultiStateThreshold;
 import org.apache.poi.hssf.record.cf.Threshold;
 import org.apache.poi.ss.usermodel.ConditionalFormattingThreshold;
 
@@ -76,6 +77,6 @@ public final class HSSFIconMultiStateFormatting implements org.apache.poi.ss.use
     }
 
     public HSSFConditionalFormattingThreshold createThreshold() {
-        return new HSSFConditionalFormattingThreshold(new Threshold(), sheet);
+        return new HSSFConditionalFormattingThreshold(new IconMultiStateThreshold(), sheet);
     }
 }
index 697f350c7e17beea1d7173bdc2b94e1de47e3473..4e508c36f05fce6cc8c8127228b1fb26ba7305ac 100644 (file)
@@ -38,8 +38,17 @@ public final class TestHSSFConditionalFormatting extends BaseTestConditionalForm
     }
     protected void assertColour(String hexExpected, Color actual) {
         assertNotNull("Colour must be given", actual);
-        HSSFColor colour = (HSSFColor)actual;
-        assertEquals(hexExpected, colour.getHexString());
+        if (actual instanceof HSSFColor) {
+            HSSFColor colour = (HSSFColor)actual;
+            assertEquals(hexExpected, colour.getHexString());
+        } else {
+            HSSFExtendedColor colour = (HSSFExtendedColor)actual;
+            if (hexExpected.length() == 8) {
+                assertEquals(hexExpected, colour.getARGBHex());
+            } else {
+                assertEquals(hexExpected, colour.getARGBHex().substring(2));
+            }
+        }
     }
 
     public void testRead() {
index 0d4c9d0520cb2262dda2f515b733f0e02f05d8c3..191e703898b8fc642e9c322f65fddac54ad2681a 100644 (file)
@@ -813,9 +813,6 @@ public abstract class BaseTestConditionalFormatting extends TestCase {
         assertEquals(null, cr.getFormula1());\r
         assertEquals(null, cr.getFormula2());\r
         \r
-// TODO Finish HSSF\r
-if (cr instanceof HSSFConditionalFormattingRule) return;\r
-        \r
         ColorScaleFormatting color = cr.getColorScaleFormatting();\r
         assertNotNull(color);\r
         assertNotNull(color.getColors());\r