More on XSSFColor and ARGB vs RGB for bug #50299 - provide methods to let you get at either 3 byte RGB, or 4 byte ARGB, whichever you prefer for your needs.

Includes the new patch from bug #50299 for 3 colour RGB black/white being inverted from Excel


git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1074703 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Nick Burch 2011-02-25 21:21:45 +00:00
parent 3937b2f310
commit 5792826402
5 changed files with 261 additions and 37 deletions

View File

@ -34,6 +34,7 @@
<changes>
<release version="3.8-beta1" date="2010-??-??">
<action dev="poi-developers" type="fix">50299 - More XSSFColor updates for ARGB vs RGB</action>
<action dev="poi-developers" type="fix">50581 - Use stax:stax-api instead of org.apache.geronimo.specs:geronimo-stax-api_1.0_spec</action>
<action dev="poi-developers" type="fix">50786 - Fix XSSFColor to fetch the RGB values of old-style indexed colours</action>
<action dev="poi-developers" type="fix">50299 - Fix XSSFColor fetching of white and black background themes</action>

View File

@ -1452,6 +1452,7 @@ public class XSSFCellStyle implements CellStyle {
*/
private void extractColorFromTheme(XSSFColor originalColor){
XSSFColor themeColor = _theme.getThemeColor(originalColor.getTheme());
originalColor.setRgb(themeColor.getRgb());
// Set the raw colour, not the adjusted one
originalColor.setRgb(themeColor.getCTColor().getRgb());
}
}

View File

@ -80,46 +80,106 @@ public class XSSFColor implements Color {
ctColor.setIndexed(indexed);
}
/**
* Standard Red Green Blue ctColor value (RGB).
* If there was an A (Alpha) value, it will be stripped.
*/
public byte[] getRgb() {
byte[] rgb = getRGBOrARGB();
if(rgb == null) return null;
if(rgb.length == 4) {
// Need to trim off the alpha
byte[] tmp = new byte[3];
System.arraycopy(rgb, 1, tmp, 0, 3);
return tmp;
} else {
return rgb;
}
}
/**
* Standard Alpha Red Green Blue ctColor value (ARGB).
*/
public byte[] getARgb() {
byte[] rgb = getRGBOrARGB();
if(rgb == null) return null;
if(rgb.length == 3) {
// Pad with the default Alpha
byte[] tmp = new byte[4];
tmp[0] = -1;
System.arraycopy(rgb, 0, tmp, 1, 3);
return tmp;
} else {
return rgb;
}
}
private byte[] getRGBOrARGB() {
byte[] rgb = null;
if (ctColor.isSetIndexed() && ctColor.getIndexed() > 0) {
HSSFColor indexed = HSSFColor.getIndexHash().get((int) ctColor.getIndexed());
if (indexed != null) {
rgb = new byte[3];
rgb[0] = (byte) indexed.getTriplet()[0];
rgb[1] = (byte) indexed.getTriplet()[1];
rgb[2] = (byte) indexed.getTriplet()[2];
return rgb;
}
}
if (!ctColor.isSetRgb()) {
// No colour is available, sorry
return null;
}
// Grab the colour
rgb = ctColor.getRgb();
if(rgb.length == 4) {
// Good to go, return it as-is
return rgb;
}
// For RGB colours, but not ARGB (we think...)
// Excel gets black and white the wrong way around, so switch them
if (rgb[0] == 0 && rgb[1] == 0 && rgb[2] == 0) {
rgb = new byte[] {-1, -1, -1};
}
else if (rgb[0] == -1 && rgb[1] == -1 && rgb[2] == -1) {
rgb = new byte[] {0, 0, 0};
}
return rgb;
}
/**
* Standard Alpha Red Green Blue ctColor value (ARGB).
* Standard Red Green Blue ctColor value (RGB) with applied tint.
* Alpha values are ignored.
*/
public byte[] getRgb() {
if(ctColor.isSetIndexed() && ctColor.getIndexed() > 0) {
HSSFColor indexed = HSSFColor.getIndexHash().get((int)ctColor.getIndexed());
if(indexed != null) {
// Convert it to ARGB form
byte[] rgb = new byte[4];
rgb[0] = 0;
rgb[1] = (byte)indexed.getTriplet()[0];
rgb[2] = (byte)indexed.getTriplet()[1];
rgb[3] = (byte)indexed.getTriplet()[2];
return rgb;
} else {
// Your indexed value isn't a standard one, sorry...
return null;
}
}
return ctColor.getRgb();
}
public byte[] getRgbWithTint() {
byte[] rgb = ctColor.getRgb();
if (rgb != null) {
if(rgb.length == 4) {
byte[] tmp = new byte[3];
System.arraycopy(rgb, 1, tmp, 0, 3);
rgb = tmp;
}
for (int i = 0; i < rgb.length; i++){
rgb[i] = applyTint(rgb[i] & 0xFF, ctColor.getTint());
}
}
return rgb;
}
/**
* Standard Alpha Red Green Blue ctColor value (ARGB) with applied tint.
* Return the ARGB value in hex format, eg FF00FF00.
* Works for both regular and indexed colours.
*/
public byte[] getRgbWithTint() {
byte[] rgb =ctColor.getRgb();
for(int i = 0; i < rgb.length; i++){
rgb[i] = applyTint(rgb[i] & 0xFF, ctColor.getTint());
}
return rgb;
}
/**
* Return the ARGB value in hex format, eg FF00FF00.
* Works for both regular and indexed colours.
*/
public String getARGBHex() {
StringBuffer sb = new StringBuffer();
byte[] rgb = getRgb();
byte[] rgb = getARgb();
if(rgb == null) {
return null;
}

View File

@ -696,7 +696,8 @@ public final class TestXSSFBugs extends BaseTestBugzillaIssues {
}
// Check one bit in detail
// TODO Is this correct, shouldn't one be white and one black?
// Check that we get back foreground=0 for the theme colours,
// and background=64 for the auto colouring
Sheet s = wb.getSheetAt(0);
assertEquals(0, s.getRow(0).getCell(8).getCellStyle().getFillForegroundColor());
assertEquals(64, s.getRow(0).getCell(8).getCellStyle().getFillBackgroundColor());
@ -721,13 +722,15 @@ public final class TestXSSFBugs extends BaseTestBugzillaIssues {
assertEquals(42, cs.getFillForegroundColor());
assertEquals(42, cs.getFillForegroundColorColor().getIndexed());
assertNotNull(cs.getFillForegroundColorColor().getRgb());
assertEquals("00CCFFCC", cs.getFillForegroundColorColor().getARGBHex());
assertEquals("FFCCFFCC", cs.getFillForegroundColorColor().getARGBHex());
}
/**
* Fonts where their colours come from the theme rather
* then being set explicitly still should allow the
* fetching of the RGB
* fetching of the RGB.
* TODO Allow XSSFFont to get at the themes table, so it can do
* the same trick that XSSFCellStyle does with theme colours
*/
public void DISABLEDtest50784() throws Exception {
XSSFWorkbook wb = XSSFTestDataSamples.openSampleWorkbook("50784-font_theme_colours.xlsx");

View File

@ -0,0 +1,159 @@
/* ====================================================================
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.xssf.usermodel;
import junit.framework.TestCase;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.XSSFITestDataProvider;
import org.apache.poi.xssf.XSSFTestDataSamples;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTBooleanProperty;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTColor;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTFont;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTFontName;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTFontScheme;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTFontSize;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTIntProperty;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTUnderlineProperty;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTVerticalAlignFontProperty;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.STFontScheme;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.STUnderlineValues;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.STVerticalAlignRun;
public final class TestXSSFColor extends TestCase {
public void testIndexedColour() throws Exception {
XSSFWorkbook wb = XSSFTestDataSamples.openSampleWorkbook("48779.xlsx");
// Check the CTColor is as expected
XSSFColor indexed = wb.getCellStyleAt((short)1).getFillBackgroundXSSFColor();
assertEquals(true, indexed.getCTColor().isSetIndexed());
assertEquals(64, indexed.getCTColor().getIndexed());
assertEquals(false, indexed.getCTColor().isSetRgb());
assertEquals(null, indexed.getCTColor().getRgb());
// Now check the XSSFColor
// Note - 64 is a special "auto" one with no rgb equiv
assertEquals(64, indexed.getIndexed());
assertEquals(null, indexed.getRgb());
assertEquals(null, indexed.getRgbWithTint());
assertEquals(null, indexed.getARGBHex());
// Now move to one with indexed rgb values
indexed.setIndexed(59);
assertEquals(true, indexed.getCTColor().isSetIndexed());
assertEquals(59, indexed.getCTColor().getIndexed());
assertEquals(false, indexed.getCTColor().isSetRgb());
assertEquals(null, indexed.getCTColor().getRgb());
assertEquals(59, indexed.getIndexed());
assertEquals("FF333300", indexed.getARGBHex());
assertEquals(3, indexed.getRgb().length);
assertEquals(0x33, indexed.getRgb()[0]);
assertEquals(0x33, indexed.getRgb()[1]);
assertEquals(0x00, indexed.getRgb()[2]);
assertEquals(4, indexed.getARgb().length);
assertEquals(-1, indexed.getARgb()[0]);
assertEquals(0x33, indexed.getARgb()[1]);
assertEquals(0x33, indexed.getARgb()[2]);
assertEquals(0x00, indexed.getARgb()[3]);
// You don't get tinted indexed colours, sorry...
assertEquals(null, indexed.getRgbWithTint());
}
public void testRGBColour() throws Exception {
XSSFWorkbook wb = XSSFTestDataSamples.openSampleWorkbook("50299.xlsx");
// Check the CTColor is as expected
XSSFColor rgb3 = wb.getCellStyleAt((short)25).getFillForegroundXSSFColor();
assertEquals(false, rgb3.getCTColor().isSetIndexed());
assertEquals(0, rgb3.getCTColor().getIndexed());
assertEquals(true, rgb3.getCTColor().isSetTint());
assertEquals(-0.34999, rgb3.getCTColor().getTint(), 0.00001);
assertEquals(true, rgb3.getCTColor().isSetRgb());
assertEquals(3, rgb3.getCTColor().getRgb().length);
// Now check the XSSFColor
assertEquals(0, rgb3.getIndexed());
assertEquals(-0.34999, rgb3.getTint(), 0.00001);
assertEquals("FFFFFFFF", rgb3.getARGBHex());
assertEquals(3, rgb3.getRgb().length);
assertEquals(-1, rgb3.getRgb()[0]);
assertEquals(-1, rgb3.getRgb()[1]);
assertEquals(-1, rgb3.getRgb()[2]);
assertEquals(4, rgb3.getARgb().length);
assertEquals(-1, rgb3.getARgb()[0]);
assertEquals(-1, rgb3.getARgb()[1]);
assertEquals(-1, rgb3.getARgb()[2]);
assertEquals(-1, rgb3.getARgb()[3]);
// Tint doesn't have the alpha
assertEquals(3, rgb3.getRgbWithTint().length);
assertEquals(0, rgb3.getRgbWithTint()[0]);
assertEquals(0, rgb3.getRgbWithTint()[1]);
assertEquals(0, rgb3.getRgbWithTint()[2]);
}
public void testARGBColour() throws Exception {
XSSFWorkbook wb = XSSFTestDataSamples.openSampleWorkbook("48779.xlsx");
// Check the CTColor is as expected
XSSFColor rgb4 = wb.getCellStyleAt((short)1).getFillForegroundXSSFColor();
assertEquals(false, rgb4.getCTColor().isSetIndexed());
assertEquals(0, rgb4.getCTColor().getIndexed());
assertEquals(true, rgb4.getCTColor().isSetRgb());
assertEquals(4, rgb4.getCTColor().getRgb().length);
// Now check the XSSFColor
assertEquals(0, rgb4.getIndexed());
assertEquals(0.0, rgb4.getTint());
assertEquals("FFFF0000", rgb4.getARGBHex());
assertEquals(3, rgb4.getRgb().length);
assertEquals(-1, rgb4.getRgb()[0]);
assertEquals(0, rgb4.getRgb()[1]);
assertEquals(0, rgb4.getRgb()[2]);
assertEquals(4, rgb4.getARgb().length);
assertEquals(-1, rgb4.getARgb()[0]);
assertEquals(-1, rgb4.getARgb()[1]);
assertEquals(0, rgb4.getARgb()[2]);
assertEquals(0, rgb4.getARgb()[3]);
// Tint doesn't have the alpha
assertEquals(3, rgb4.getRgbWithTint().length);
assertEquals(-1, rgb4.getRgbWithTint()[0]);
assertEquals(0, rgb4.getRgbWithTint()[1]);
assertEquals(0, rgb4.getRgbWithTint()[2]);
// Turn on tinting, and check it behaves
// TODO These values are suspected to be wrong...
rgb4.setTint(0.4);
assertEquals(0.4, rgb4.getTint());
assertEquals(3, rgb4.getRgbWithTint().length);
assertEquals(-1, rgb4.getRgbWithTint()[0]);
assertEquals(102, rgb4.getRgbWithTint()[1]);
assertEquals(102, rgb4.getRgbWithTint()[2]);
}
}