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> <changes>
<release version="3.8-beta1" date="2010-??-??"> <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">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">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> <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){ private void extractColorFromTheme(XSSFColor originalColor){
XSSFColor themeColor = _theme.getThemeColor(originalColor.getTheme()); 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); ctColor.setIndexed(indexed);
} }
/** /**
* Standard Alpha Red Green Blue ctColor value (ARGB). * Standard Red Green Blue ctColor value (RGB).
*/ * If there was an A (Alpha) value, it will be stripped.
public byte[] getRgb() { */
if(ctColor.isSetIndexed() && ctColor.getIndexed() > 0) { public byte[] getRgb() {
HSSFColor indexed = HSSFColor.getIndexHash().get((int)ctColor.getIndexed()); byte[] rgb = getRGBOrARGB();
if(indexed != null) { if(rgb == null) return null;
// Convert it to ARGB form
byte[] rgb = new byte[4]; if(rgb.length == 4) {
rgb[0] = 0; // Need to trim off the alpha
rgb[1] = (byte)indexed.getTriplet()[0]; byte[] tmp = new byte[3];
rgb[2] = (byte)indexed.getTriplet()[1]; System.arraycopy(rgb, 1, tmp, 0, 3);
rgb[3] = (byte)indexed.getTriplet()[2]; return tmp;
return rgb; } else {
} else { return rgb;
// Your indexed value isn't a standard one, sorry... }
return null; }
}
} /**
return ctColor.getRgb(); * 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) with applied tint. * Standard Red Green Blue ctColor value (RGB) with applied tint.
* Alpha values are ignored.
*/ */
public byte[] getRgbWithTint() { public byte[] getRgbWithTint() {
byte[] rgb =ctColor.getRgb(); byte[] rgb = ctColor.getRgb();
for(int i = 0; i < rgb.length; i++){ if (rgb != null) {
rgb[i] = applyTint(rgb[i] & 0xFF, ctColor.getTint()); if(rgb.length == 4) {
} byte[] tmp = new byte[3];
return rgb; 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;
}
/** /**
* Return the ARGB value in hex format, eg FF00FF00. * Return the ARGB value in hex format, eg FF00FF00.
* Works for both regular and indexed colours. * Works for both regular and indexed colours.
*/ */
public String getARGBHex() { public String getARGBHex() {
StringBuffer sb = new StringBuffer(); StringBuffer sb = new StringBuffer();
byte[] rgb = getRgb(); byte[] rgb = getARgb();
if(rgb == null) { if(rgb == null) {
return null; return null;
} }

View File

@ -696,7 +696,8 @@ public final class TestXSSFBugs extends BaseTestBugzillaIssues {
} }
// Check one bit in detail // 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); Sheet s = wb.getSheetAt(0);
assertEquals(0, s.getRow(0).getCell(8).getCellStyle().getFillForegroundColor()); assertEquals(0, s.getRow(0).getCell(8).getCellStyle().getFillForegroundColor());
assertEquals(64, s.getRow(0).getCell(8).getCellStyle().getFillBackgroundColor()); 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.getFillForegroundColor());
assertEquals(42, cs.getFillForegroundColorColor().getIndexed()); assertEquals(42, cs.getFillForegroundColorColor().getIndexed());
assertNotNull(cs.getFillForegroundColorColor().getRgb()); assertNotNull(cs.getFillForegroundColorColor().getRgb());
assertEquals("00CCFFCC", cs.getFillForegroundColorColor().getARGBHex()); assertEquals("FFCCFFCC", cs.getFillForegroundColorColor().getARGBHex());
} }
/** /**
* Fonts where their colours come from the theme rather * Fonts where their colours come from the theme rather
* then being set explicitly still should allow the * 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 { public void DISABLEDtest50784() throws Exception {
XSSFWorkbook wb = XSSFTestDataSamples.openSampleWorkbook("50784-font_theme_colours.xlsx"); 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]);
}
}