]> source.dussan.org Git - poi.git/commitdiff
Start decoding the CF color scales for HSSF
authorNick Burch <nick@apache.org>
Sun, 19 Jul 2015 04:39:17 +0000 (04:39 +0000)
committerNick Burch <nick@apache.org>
Sun, 19 Jul 2015 04:39:17 +0000 (04:39 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1691795 13f79535-47bb-0310-9956-ffa450edef68

src/java/org/apache/poi/hssf/record/CFRule12Record.java
src/java/org/apache/poi/hssf/record/cf/ColorGradientFormatting.java [new file with mode: 0644]

index c9d0f174b94cb69f6cd1412c0e52cfd691469b5b..3e72e5810eb6ba034f982d99e45e8126f52c795f 100644 (file)
@@ -19,6 +19,7 @@ package org.apache.poi.hssf.record;
 
 import java.util.Arrays;
 
+import org.apache.poi.hssf.record.cf.ColorGradientFormatting;
 import org.apache.poi.hssf.record.cf.IconMultiStateFormatting;
 import org.apache.poi.hssf.record.cf.Threshold;
 import org.apache.poi.hssf.record.common.FtrHeader;
@@ -56,9 +57,9 @@ public final class CFRule12Record extends CFRuleBase implements FutureRecord {
     private byte[] template_params;
     
     private IconMultiStateFormatting multistate;
+    private ColorGradientFormatting color_gradient;
     
     // TODO Parse these
-    private byte[] gradient_data;
     private byte[] databar_data;
     private byte[] filter_data;
 
@@ -176,7 +177,7 @@ public final class CFRule12Record extends CFRuleBase implements FutureRecord {
         
         byte type = getConditionType();
         if (type == CONDITION_TYPE_COLOR_SCALE) {
-            gradient_data = in.readRemainder();
+            color_gradient = new ColorGradientFormatting(in);
         } else if (type == CONDITION_TYPE_DATA_BAR) {
             databar_data = in.readRemainder();
         } else if (type == CONDITION_TYPE_FILTER) {
@@ -261,7 +262,7 @@ public final class CFRule12Record extends CFRuleBase implements FutureRecord {
         
         byte type = getConditionType();
         if (type == CONDITION_TYPE_COLOR_SCALE) {
-            out.write(gradient_data);
+            color_gradient.serialize(out);
         } else if (type == CONDITION_TYPE_DATA_BAR) {
             out.write(databar_data);
         } else if (type == CONDITION_TYPE_FILTER) {
@@ -285,7 +286,7 @@ public final class CFRule12Record extends CFRuleBase implements FutureRecord {
         
         byte type = getConditionType();
         if (type == CONDITION_TYPE_COLOR_SCALE) {
-            len += gradient_data.length;
+            len += color_gradient.getDataLength();
         } else if (type == CONDITION_TYPE_DATA_BAR) {
             len += databar_data.length;
         } else if (type == CONDITION_TYPE_FILTER) {
@@ -319,9 +320,11 @@ public final class CFRule12Record extends CFRuleBase implements FutureRecord {
         buffer.append("    .priority  =").append(priority).append("\n");
         buffer.append("    .template_type  =").append(template_type).append("\n");
         buffer.append("    .template_params=").append(HexDump.toHex(template_params)).append("\n");
-        buffer.append("    .gradient_data  =").append(HexDump.toHex(gradient_data)).append("\n");
         buffer.append("    .databar_data   =").append(HexDump.toHex(databar_data)).append("\n");
         buffer.append("    .filter_data    =").append(HexDump.toHex(filter_data)).append("\n");
+        if (color_gradient != null) {
+            buffer.append(color_gradient);
+        }
         if (multistate != null) {
             buffer.append(multistate);
         }
diff --git a/src/java/org/apache/poi/hssf/record/cf/ColorGradientFormatting.java b/src/java/org/apache/poi/hssf/record/cf/ColorGradientFormatting.java
new file mode 100644 (file)
index 0000000..12b1f71
--- /dev/null
@@ -0,0 +1,134 @@
+/* ====================================================================
+   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.record.cf;
+
+import org.apache.poi.util.BitField;
+import org.apache.poi.util.BitFieldFactory;
+import org.apache.poi.util.LittleEndianInput;
+import org.apache.poi.util.LittleEndianOutput;
+import org.apache.poi.util.POILogFactory;
+import org.apache.poi.util.POILogger;
+
+/**
+ * Color Gradient / Color Scale Conditional Formatting Rule Record.
+ * (Called Color Gradient in the file format docs, but more commonly
+ *  Color Scale in the UI)
+ */
+public final class ColorGradientFormatting implements Cloneable {
+    private static POILogger log = POILogFactory.getLogger(ColorGradientFormatting.class);
+
+    private byte options = 0;
+    private Threshold[] thresholds;
+    private byte[] colors; // TODO Decode
+    
+    private static BitField clamp = BitFieldFactory.getInstance(0x01);
+    private static BitField background = BitFieldFactory.getInstance(0x02);
+    
+    public ColorGradientFormatting() {
+        options = 3;
+        thresholds = new Threshold[3];
+    }
+    public ColorGradientFormatting(LittleEndianInput in) {
+        in.readShort(); // Ignored
+        in.readByte();  // Reserved
+        int numI = in.readByte();
+        int numG = in.readByte();
+        if (numI != numG) {
+            log.log(POILogger.WARN, "Inconsistent Color Gradient defintion, found " + numI + " vs " + numG + " entries");
+        }
+        options = in.readByte();
+        
+        // TODO Are these correct?
+        thresholds = new Threshold[numI];
+        for (int i=0; i<thresholds.length; i++) {
+            thresholds[i] = new Threshold(in);
+            in.readDouble(); // Rather pointless value...
+        }
+        // TODO Decode colors
+        colors = new byte[in.available()];
+        in.readFully(colors);
+    }
+    
+    public Threshold[] getThresholds() {
+        return thresholds;
+    }
+    public void setThresholds(Threshold[] thresholds) {
+        this.thresholds = thresholds;
+    }
+
+    // TODO Colors
+    
+    public boolean isClampToCurve() {
+        return getOptionFlag(clamp);
+    }
+    public boolean isAppliesToBackground() {
+        return getOptionFlag(background);
+    }
+    private boolean getOptionFlag(BitField field) {
+        int value = field.getValue(options);
+        return value==0 ? false : true;
+    }
+    
+    public String toString() {
+        StringBuffer buffer = new StringBuffer();
+        buffer.append("    [Color Gradient Formatting]\n");
+        buffer.append("          .clamp     = ").append(isClampToCurve()).append("\n");
+        buffer.append("          .background= ").append(isAppliesToBackground()).append("\n");
+        for (Threshold t : thresholds) {
+            buffer.append(t.toString());
+        }
+        buffer.append("    [/Color Gradient Formatting]\n");
+        return buffer.toString();
+    }
+    
+    public Object clone()  {
+      ColorGradientFormatting rec = new ColorGradientFormatting();
+      rec.options = options;
+      rec.thresholds = new Threshold[thresholds.length];
+      System.arraycopy(thresholds, 0, rec.thresholds, 0, thresholds.length);
+      // TODO Colors
+      return rec;
+    }
+    
+    public int getDataLength() {
+        int len = 6;
+        for (Threshold t : thresholds) {
+            len += t.getDataLength();
+            len += 8;
+        }
+        len += colors.length;
+        return len;
+    }
+
+    public void serialize(LittleEndianOutput out) {
+        out.writeShort(0);
+        out.writeByte(0);
+        out.writeByte(thresholds.length);
+        out.writeByte(thresholds.length);
+        out.writeByte(options);
+        
+        double step = 1d / (thresholds.length-1);
+        for (int i=0; i<thresholds.length; i++) {
+            Threshold t = thresholds[i];
+            t.serialize(out);
+            out.writeDouble(step*i);
+        }
+        
+        out.write(colors);
+    }
+}