git-svn-id: https://svn.apache.org/repos/asf/jakarta/poi/trunk@352979 13f79535-47bb-0310-9956-ffa450edef68tags/REL_1_10
@@ -0,0 +1,193 @@ | |||
/* ==================================================================== | |||
* The Apache Software License, Version 1.1 | |||
* | |||
* Copyright (c) 2002 The Apache Software Foundation. All rights | |||
* reserved. | |||
* | |||
* Redistribution and use in source and binary forms, with or without | |||
* modification, are permitted provided that the following conditions | |||
* are met: | |||
* | |||
* 1. Redistributions of source code must retain the above copyright | |||
* notice, this list of conditions and the following disclaimer. | |||
* | |||
* 2. Redistributions in binary form must reproduce the above copyright | |||
* notice, this list of conditions and the following disclaimer in | |||
* the documentation and/or other materials provided with the | |||
* distribution. | |||
* | |||
* 3. The end-user documentation included with the redistribution, | |||
* if any, must include the following acknowledgment: | |||
* "This product includes software developed by the | |||
* Apache Software Foundation (http://www.apache.org/)." | |||
* Alternately, this acknowledgment may appear in the software itself, | |||
* if and wherever such third-party acknowledgments normally appear. | |||
* | |||
* 4. The names "Apache" and "Apache Software Foundation" and | |||
* "Apache POI" must not be used to endorse or promote products | |||
* derived from this software without prior written permission. For | |||
* written permission, please contact apache@apache.org. | |||
* | |||
* 5. Products derived from this software may not be called "Apache", | |||
* "Apache POI", nor may "Apache" appear in their name, without | |||
* prior written permission of the Apache Software Foundation. | |||
* | |||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED | |||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |||
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR | |||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF | |||
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | |||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT | |||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |||
* SUCH DAMAGE. | |||
* ==================================================================== | |||
* | |||
* This software consists of voluntary contributions made by many | |||
* individuals on behalf of the Apache Software Foundation. For more | |||
* information on the Apache Software Foundation, please see | |||
* <http://www.apache.org/>. | |||
*/ | |||
package org.apache.poi.hssf.usermodel; | |||
import org.apache.poi.hssf.record.PaletteRecord; | |||
import org.apache.poi.hssf.util.HSSFColor; | |||
/** | |||
* Represents a workbook color palette. | |||
* Internally, the XLS format refers to colors using an offset into the palette | |||
* record. Thus, the first color in the palette has the index 0x8, the second | |||
* has the index 0x9, etc. through 0x40 | |||
* | |||
* @author Brian Sanders (bsanders at risklabs dot com) | |||
*/ | |||
public class HSSFPalette | |||
{ | |||
private PaletteRecord palette; | |||
protected HSSFPalette(PaletteRecord palette) | |||
{ | |||
this.palette = palette; | |||
} | |||
/** | |||
* Retrieves the color at a given index | |||
* | |||
* @param index the palette index, between 0x8 to 0x40 inclusive | |||
* @return the color, or null if the index is not populated | |||
*/ | |||
public HSSFColor getColor(short index) | |||
{ | |||
byte[] b = palette.getColor(index); | |||
if (b != null) | |||
{ | |||
return new CustomColor(index, b); | |||
} | |||
return null; | |||
} | |||
/** | |||
* Finds the first occurance of a given color | |||
* | |||
* @param red the RGB red component, between 0 and 255 inclusive | |||
* @param green the RGB green component, between 0 and 255 inclusive | |||
* @param blue the RGB blue component, between 0 and 255 inclusive | |||
* @return the color, or null if the color does not exist in this palette | |||
*/ | |||
public HSSFColor findColor(byte red, byte green, byte blue) | |||
{ | |||
byte[] b = palette.getColor(PaletteRecord.FIRST_COLOR_INDEX); | |||
for (short i = (short) PaletteRecord.FIRST_COLOR_INDEX; b != null; | |||
b = palette.getColor(++i)) | |||
{ | |||
if (b[0] == red && b[1] == blue && b[2] == green) | |||
{ | |||
return new CustomColor(i, b); | |||
} | |||
} | |||
return null; | |||
} | |||
/** | |||
* Sets the color at the given offset | |||
* | |||
* @param index the palette index, between 0x8 to 0x40 inclusive | |||
* @param red the RGB red component, between 0 and 255 inclusive | |||
* @param green the RGB green component, between 0 and 255 inclusive | |||
* @param blue the RGB blue component, between 0 and 255 inclusive | |||
*/ | |||
public void setColorAtIndex(short index, byte red, byte green, byte blue) | |||
{ | |||
palette.setColor(index, red, green, blue); | |||
} | |||
private static class CustomColor extends HSSFColor | |||
{ | |||
private short byteOffset; | |||
private byte red; | |||
private byte green; | |||
private byte blue; | |||
private CustomColor(short byteOffset, byte[] colors) | |||
{ | |||
this(byteOffset, colors[0], colors[1], colors[2]); | |||
} | |||
private CustomColor(short byteOffset, byte red, byte green, byte blue) | |||
{ | |||
this.byteOffset = byteOffset; | |||
this.red = red; | |||
this.green = green; | |||
this.blue = blue; | |||
} | |||
public short getIndex() | |||
{ | |||
return byteOffset; | |||
} | |||
public short[] getTriplet() | |||
{ | |||
return new short[] | |||
{ | |||
(short) (red & 0xff), | |||
(short) (green & 0xff), | |||
(short) (blue & 0xff) | |||
}; | |||
} | |||
public String getHexString() | |||
{ | |||
StringBuffer sb = new StringBuffer(); | |||
sb.append(getGnumericPart(red)); | |||
sb.append(':'); | |||
sb.append(getGnumericPart(green)); | |||
sb.append(':'); | |||
sb.append(getGnumericPart(blue)); | |||
return sb.toString(); | |||
} | |||
private String getGnumericPart(byte color) | |||
{ | |||
String s; | |||
if (color == 0) | |||
{ | |||
s = "0"; | |||
} | |||
else | |||
{ | |||
int c = color & 0xff; //as unsigned | |||
c = (c << 8) | c; //pad to 16-bit | |||
s = Integer.toHexString(c).toUpperCase(); | |||
while (s.length() < 4) | |||
{ | |||
s = "0" + s; | |||
} | |||
} | |||
return s; | |||
} | |||
} | |||
} |
@@ -0,0 +1,96 @@ | |||
/* ==================================================================== | |||
* The Apache Software License, Version 1.1 | |||
* | |||
* Copyright (c) 2002 The Apache Software Foundation. All rights | |||
* reserved. | |||
* | |||
* Redistribution and use in source and binary forms, with or without | |||
* modification, are permitted provided that the following conditions | |||
* are met: | |||
* | |||
* 1. Redistributions of source code must retain the above copyright | |||
* notice, this list of conditions and the following disclaimer. | |||
* | |||
* 2. Redistributions in binary form must reproduce the above copyright | |||
* notice, this list of conditions and the following disclaimer in | |||
* the documentation and/or other materials provided with the | |||
* distribution. | |||
* | |||
* 3. The end-user documentation included with the redistribution, | |||
* if any, must include the following acknowledgment: | |||
* "This product includes software developed by the | |||
* Apache Software Foundation (http://www.apache.org/)." | |||
* Alternately, this acknowledgment may appear in the software itself, | |||
* if and wherever such third-party acknowledgments normally appear. | |||
* | |||
* 4. The names "Apache" and "Apache Software Foundation" and | |||
* "Apache POI" must not be used to endorse or promote products | |||
* derived from this software without prior written permission. For | |||
* written permission, please contact apache@apache.org. | |||
* | |||
* 5. Products derived from this software may not be called "Apache", | |||
* "Apache POI", nor may "Apache" appear in their name, without | |||
* prior written permission of the Apache Software Foundation. | |||
* | |||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED | |||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |||
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR | |||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF | |||
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | |||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT | |||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |||
* SUCH DAMAGE. | |||
* ==================================================================== | |||
* | |||
* This software consists of voluntary contributions made by many | |||
* individuals on behalf of the Apache Software Foundation. For more | |||
* information on the Apache Software Foundation, please see | |||
* <http://www.apache.org/>. | |||
*/ | |||
package org.apache.poi.hssf.record; | |||
import java.util.Iterator; | |||
import java.util.Map; | |||
import junit.framework.TestCase; | |||
import org.apache.poi.hssf.util.HSSFColor; | |||
/** | |||
* Verifies that custom palette editing works correctly | |||
* | |||
* @author Brian Sanders (bsanders at risklabs dot com) | |||
*/ | |||
public class TestPaletteRecord extends TestCase | |||
{ | |||
public TestPaletteRecord(String name) | |||
{ | |||
super(name); | |||
} | |||
/** | |||
* Tests that the default palette matches the constants of HSSFColor | |||
*/ | |||
public void testDefaultPalette() | |||
{ | |||
PaletteRecord palette = new PaletteRecord(PaletteRecord.sid); | |||
//make sure all the HSSFColor constants match | |||
Map colors = HSSFColor.getIndexHash(); | |||
Iterator indexes = colors.keySet().iterator(); | |||
while (indexes.hasNext()) | |||
{ | |||
Integer index = (Integer) indexes.next(); | |||
HSSFColor c = (HSSFColor) colors.get(index); | |||
short[] rgbTriplet = c.getTriplet(); | |||
byte[] paletteTriplet = palette.getColor(index.shortValue()); | |||
String msg = "Expected HSSFColor constant to match PaletteRecord at index 0x" | |||
+ Integer.toHexString(c.getIndex()); | |||
assertEquals(msg, rgbTriplet[0], paletteTriplet[0] & 0xff); | |||
assertEquals(msg, rgbTriplet[1], paletteTriplet[1] & 0xff); | |||
assertEquals(msg, rgbTriplet[2], paletteTriplet[2] & 0xff); | |||
} | |||
} | |||
} |
@@ -0,0 +1,187 @@ | |||
/* ==================================================================== | |||
* The Apache Software License, Version 1.1 | |||
* | |||
* Copyright (c) 2002 The Apache Software Foundation. All rights | |||
* reserved. | |||
* | |||
* Redistribution and use in source and binary forms, with or without | |||
* modification, are permitted provided that the following conditions | |||
* are met: | |||
* | |||
* 1. Redistributions of source code must retain the above copyright | |||
* notice, this list of conditions and the following disclaimer. | |||
* | |||
* 2. Redistributions in binary form must reproduce the above copyright | |||
* notice, this list of conditions and the following disclaimer in | |||
* the documentation and/or other materials provided with the | |||
* distribution. | |||
* | |||
* 3. The end-user documentation included with the redistribution, | |||
* if any, must include the following acknowledgment: | |||
* "This product includes software developed by the | |||
* Apache Software Foundation (http://www.apache.org/)." | |||
* Alternately, this acknowledgment may appear in the software itself, | |||
* if and wherever such third-party acknowledgments normally appear. | |||
* | |||
* 4. The names "Apache" and "Apache Software Foundation" and | |||
* "Apache POI" must not be used to endorse or promote products | |||
* derived from this software without prior written permission. For | |||
* written permission, please contact apache@apache.org. | |||
* | |||
* 5. Products derived from this software may not be called "Apache", | |||
* "Apache POI", nor may "Apache" appear in their name, without | |||
* prior written permission of the Apache Software Foundation. | |||
* | |||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED | |||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |||
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR | |||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF | |||
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | |||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT | |||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |||
* SUCH DAMAGE. | |||
* ==================================================================== | |||
* | |||
* This software consists of voluntary contributions made by many | |||
* individuals on behalf of the Apache Software Foundation. For more | |||
* information on the Apache Software Foundation, please see | |||
* <http://www.apache.org/>. | |||
*/ | |||
package org.apache.poi.hssf.usermodel; | |||
import java.io.File; | |||
import java.io.FileInputStream; | |||
import java.io.FileOutputStream; | |||
import java.io.IOException; | |||
import java.util.Iterator; | |||
import java.util.Map; | |||
import junit.framework.TestCase; | |||
import org.apache.poi.hssf.record.PaletteRecord; | |||
import org.apache.poi.hssf.util.HSSFColor; | |||
/** | |||
* @author Brian Sanders (bsanders at risklabs dot com) | |||
*/ | |||
public class TestHSSFPalette extends TestCase | |||
{ | |||
private PaletteRecord palette; | |||
private HSSFPalette hssfPalette; | |||
public TestHSSFPalette(String name) | |||
{ | |||
super(name); | |||
} | |||
public void setUp() | |||
{ | |||
palette = new PaletteRecord(PaletteRecord.sid); | |||
hssfPalette = new HSSFPalette(palette); | |||
} | |||
/** | |||
* Verifies that a custom palette can be created, saved, and reloaded | |||
*/ | |||
public void testCustomPalette() throws IOException | |||
{ | |||
//reading sample xls | |||
String dir = System.getProperty("HSSF.testdata.path"); | |||
File sample = new File(dir + "/Simple.xls"); | |||
assertTrue("Simple.xls exists and is readable", sample.canRead()); | |||
FileInputStream fis = new FileInputStream(sample); | |||
HSSFWorkbook book = new HSSFWorkbook(fis); | |||
fis.close(); | |||
//creating custom palette | |||
HSSFPalette palette = book.getCustomPalette(); | |||
palette.setColorAtIndex((short) 0x12, (byte) 101, (byte) 230, (byte) 100); | |||
palette.setColorAtIndex((short) 0x3b, (byte) 0, (byte) 255, (byte) 52); | |||
//writing to disk; reading in and verifying palette | |||
File temp = File.createTempFile("testCustomPalette", ".xls"); | |||
FileOutputStream fos = new FileOutputStream(temp); | |||
book.write(fos); | |||
fos.close(); | |||
fis = new FileInputStream(temp); | |||
book = new HSSFWorkbook(fis); | |||
fis.close(); | |||
temp.delete(); | |||
palette = book.getCustomPalette(); | |||
HSSFColor color = palette.getColor(HSSFColor.CORAL.index); //unmodified | |||
assertNotNull("Unexpected null in custom palette (unmodified index)", color); | |||
short[] expectedRGB = HSSFColor.CORAL.triplet; | |||
short[] actualRGB = color.getTriplet(); | |||
String msg = "Expected palette position to remain unmodified"; | |||
assertEquals(msg, expectedRGB[0], actualRGB[0]); | |||
assertEquals(msg, expectedRGB[1], actualRGB[1]); | |||
assertEquals(msg, expectedRGB[2], actualRGB[2]); | |||
color = palette.getColor((short) 0x12); | |||
assertNotNull("Unexpected null in custom palette (modified)", color); | |||
actualRGB = color.getTriplet(); | |||
msg = "Expected palette modification to be preserved across save"; | |||
assertEquals(msg, (short) 101, actualRGB[0]); | |||
assertEquals(msg, (short) 230, actualRGB[1]); | |||
assertEquals(msg, (short) 100, actualRGB[2]); | |||
} | |||
/** | |||
* Verifies that the generated gnumeric-format string values match the | |||
* hardcoded values in the HSSFColor default color palette | |||
*/ | |||
public void testGnumericStrings() | |||
{ | |||
compareToDefaults(new ColorComparator() { | |||
public void compare(HSSFColor expected, HSSFColor palette) | |||
{ | |||
assertEquals(expected.getHexString(), palette.getHexString()); | |||
} | |||
}); | |||
} | |||
/** | |||
* Verifies that the palette handles invalid palette indexes | |||
*/ | |||
public void testBadIndexes() | |||
{ | |||
//too small | |||
hssfPalette.setColorAtIndex((short) 2, (byte) 255, (byte) 255, (byte) 255); | |||
//too large | |||
hssfPalette.setColorAtIndex((short) 0x45, (byte) 255, (byte) 255, (byte) 255); | |||
//should still match defaults; | |||
compareToDefaults(new ColorComparator() { | |||
public void compare(HSSFColor expected, HSSFColor palette) | |||
{ | |||
short[] s1 = expected.getTriplet(); | |||
short[] s2 = palette.getTriplet(); | |||
assertEquals(s1[0], s2[0]); | |||
assertEquals(s1[1], s2[1]); | |||
assertEquals(s1[2], s2[2]); | |||
} | |||
}); | |||
} | |||
private void compareToDefaults(ColorComparator c) | |||
{ | |||
Map colors = HSSFColor.getIndexHash(); | |||
Iterator it = colors.keySet().iterator(); | |||
while (it.hasNext()) | |||
{ | |||
Number index = (Number) it.next(); | |||
HSSFColor expectedColor = (HSSFColor) colors.get(index); | |||
HSSFColor paletteColor = hssfPalette.getColor(index.shortValue()); | |||
c.compare(expectedColor, paletteColor); | |||
} | |||
} | |||
private static interface ColorComparator | |||
{ | |||
void compare(HSSFColor expected, HSSFColor palette); | |||
} | |||
} |