#58130 HSSF CF Color Scale color support

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1691865 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Nick Burch 2015-07-20 00:47:27 +00:00
parent eee0fb2835
commit 130fe24870
6 changed files with 217 additions and 21 deletions

View 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);
}
}

View 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() {

View File

@ -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);
}
}

View 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);
}
}

View 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() {

View File

@ -813,9 +813,6 @@ public abstract class BaseTestConditionalFormatting extends TestCase {
assertEquals(null, cr.getFormula1());
assertEquals(null, cr.getFormula2());
// TODO Finish HSSF
if (cr instanceof HSSFConditionalFormattingRule) return;
ColorScaleFormatting color = cr.getColorScaleFormatting();
assertNotNull(color);
assertNotNull(color.getColors());