Bug 60898 - XSSFColor's getARGB() method returns a wrong color value when a workbook has a custom indexed color

teach XSSFColor and most things that create instances about indexed colors.

Null is a valid value for IndexedColorMap instances - the existing built-in default colors are used.

Whenever a workbook style is accessible in the call hierarchy its color mappings are passed down now.

Thanks for the unit test in the issue, it now passes.

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1796359 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Greg Woolsey 2017-05-26 23:14:48 +00:00
parent 585d77c9cf
commit c844803b66
29 changed files with 426 additions and 130 deletions

View File

@ -22,6 +22,7 @@ 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_RGB;
import static org.apache.poi.hssf.record.common.ExtendedColor.TYPE_THEMED; import static org.apache.poi.hssf.record.common.ExtendedColor.TYPE_THEMED;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.usermodel.ExtendedColor; import org.apache.poi.ss.usermodel.ExtendedColor;
/** /**
@ -106,4 +107,19 @@ public class HSSFExtendedColor extends ExtendedColor {
public void setTint(double tint) { public void setTint(double tint) {
color.setTint(tint); color.setTint(tint);
} }
protected byte[] getIndexedRGB() {
if (isIndexed() && getIndex() > 0) {
int indexNum = getIndex();
HSSFColor indexed = HSSFColor.getIndexHash().get(indexNum);
if (indexed != null) {
byte[] rgb = new byte[3];
rgb[0] = (byte) indexed.getTriplet()[0];
rgb[1] = (byte) indexed.getTriplet()[1];
rgb[2] = (byte) indexed.getTriplet()[2];
return rgb;
}
} // else
return null;
}
} }

View File

@ -18,77 +18,80 @@ package org.apache.poi.ss.usermodel;
import java.util.Locale; import java.util.Locale;
import org.apache.poi.hssf.util.HSSFColor;
/** /**
* Represents a XSSF-style color (based on either a * Represents a XSSF-style color (based on either a
* {@link org.apache.poi.xssf.usermodel.XSSFColor} or a * {@link org.apache.poi.xssf.usermodel.XSSFColor} or a
* {@link org.apache.poi.hssf.record.common.ExtendedColor} * {@link org.apache.poi.hssf.record.common.ExtendedColor}
*/ */
public abstract class ExtendedColor implements Color { public abstract class ExtendedColor implements Color {
/**
*
* @param clr awt Color to set
*/
protected void setColor(java.awt.Color clr) { protected void setColor(java.awt.Color clr) {
setRGB(new byte[]{(byte)clr.getRed(), (byte)clr.getGreen(), (byte)clr.getBlue()}); setRGB(new byte[]{(byte)clr.getRed(), (byte)clr.getGreen(), (byte)clr.getBlue()});
} }
/** /**
* A boolean value indicating the color is automatic * @return true if the color is automatic
*/ */
public abstract boolean isAuto(); public abstract boolean isAuto();
/** /**
* A boolean value indicating the color is indexed * @return true if the color is indexed
*/ */
public abstract boolean isIndexed(); public abstract boolean isIndexed();
/** /**
* A boolean value indicating the color is RGB / ARGB * @return true if the color is RGB / ARGB
*/ */
public abstract boolean isRGB(); public abstract boolean isRGB();
/** /**
* A boolean value indicating the color is from a Theme * @return true if the color is from a Theme
*/ */
public abstract boolean isThemed(); public abstract boolean isThemed();
/** /**
* Indexed Color value, if {@link #isIndexed()} is true * @return Indexed Color index value, if {@link #isIndexed()} is true
*/ */
public abstract short getIndex(); public abstract short getIndex();
/** /**
* Index of Theme color, if {@link #isThemed()} is true * @return Index of Theme color, if {@link #isThemed()} is true
*/ */
public abstract int getTheme(); public abstract int getTheme();
/** /**
* Standard Red Green Blue ctColor value (RGB). * @return Standard Red Green Blue ctColor value (RGB) bytes.
* If there was an A (Alpha) value, it will be stripped. * If there was an A (Alpha) value, it will be stripped.
*/ */
public abstract byte[] getRGB(); public abstract byte[] getRGB();
/** /**
* Standard Alpha Red Green Blue ctColor value (ARGB). * @return Standard Alpha Red Green Blue ctColor value (ARGB) bytes.
*/ */
public abstract byte[] getARGB(); public abstract byte[] getARGB();
/** /**
* RGB or ARGB or null * @return RGB or ARGB bytes or null
*/ */
protected abstract byte[] getStoredRBG(); protected abstract byte[] getStoredRBG();
/** /**
* Sets the Red Green Blue or Alpha Red Green Blue * Sets the Red Green Blue or Alpha Red Green Blue
* @param rgb bytes
*/ */
public abstract void setRGB(byte[] rgb); public abstract void setRGB(byte[] rgb);
/**
* @return RGB or ARGB bytes, either stored or by index
*/
protected byte[] getRGBOrARGB() { protected byte[] getRGBOrARGB() {
if (isIndexed() && getIndex() > 0) { if (isIndexed() && getIndex() > 0) {
int indexNum = getIndex(); byte[] rgb = getIndexedRGB();
HSSFColor indexed = HSSFColor.getIndexHash().get(indexNum); if (rgb != null) {
if (indexed != null) {
byte[] rgb = new byte[3];
rgb[0] = (byte) indexed.getTriplet()[0];
rgb[1] = (byte) indexed.getTriplet()[1];
rgb[2] = (byte) indexed.getTriplet()[2];
return rgb; return rgb;
} }
} }
@ -98,7 +101,12 @@ public abstract class ExtendedColor implements Color {
} }
/** /**
* Standard Red Green Blue ctColor value (RGB) with applied tint. * @return index color RGB bytes, if {@link #isIndexed()} == true, null if not indexed or index is invalid
*/
protected abstract byte[] getIndexedRGB();
/**
* @return Standard Red Green Blue ctColor value (RGB) bytes with applied tint.
* Alpha values are ignored. * Alpha values are ignored.
*/ */
public byte[] getRGBWithTint() { public byte[] getRGBWithTint() {
@ -118,7 +126,7 @@ public abstract class ExtendedColor implements Color {
} }
/** /**
* Return the ARGB value in hex format, eg FF00FF00. * @return the ARGB value in hex string format, eg FF00FF00.
* Works for both regular and indexed colours. * Works for both regular and indexed colours.
*/ */
public String getARGBHex() { public String getARGBHex() {
@ -142,6 +150,7 @@ public abstract class ExtendedColor implements Color {
/** /**
* Sets the ARGB value from hex format, eg FF0077FF. * Sets the ARGB value from hex format, eg FF0077FF.
* Only works for regular (non-indexed) colours * Only works for regular (non-indexed) colours
* @param argb color ARGB hex string
*/ */
public void setARGBHex(String argb) { public void setARGBHex(String argb) {
if (argb.length() == 6 || argb.length() == 8) { if (argb.length() == 6 || argb.length() == 8) {

View File

@ -31,7 +31,15 @@ package org.apache.poi.ss.usermodel;
*/ */
public enum IndexedColors { public enum IndexedColors {
// 0-7? // 0-7 duplicates of 8-15 for compatibility (OOXML spec pt.1 sec. 18.8.27)
BLACK1(0),
WHITE1(1),
RED1(2),
BRIGHT_GREEN1(3),
BLUE1(4),
YELLOW1(5),
PINK1(6),
TURQUOISE1(7),
BLACK(8), BLACK(8),
WHITE(9), WHITE(9),
RED(10), RED(10),
@ -51,7 +59,7 @@ public enum IndexedColors {
CORNFLOWER_BLUE(24), CORNFLOWER_BLUE(24),
MAROON(25), MAROON(25),
LEMON_CHIFFON(26), LEMON_CHIFFON(26),
// 27? LIGHT_TURQUOISE1(27),
ORCHID(28), ORCHID(28),
CORAL(29), CORAL(29),
ROYAL_BLUE(30), ROYAL_BLUE(30),

View File

@ -41,6 +41,9 @@ import org.apache.poi.ss.usermodel.FontFamily;
import org.apache.poi.ss.usermodel.FontScheme; import org.apache.poi.ss.usermodel.FontScheme;
import org.apache.poi.ss.usermodel.TableStyle; import org.apache.poi.ss.usermodel.TableStyle;
import org.apache.poi.util.Internal; import org.apache.poi.util.Internal;
import org.apache.poi.xssf.usermodel.CustomIndexedColorMap;
import org.apache.poi.xssf.usermodel.DefaultIndexedColorMap;
import org.apache.poi.xssf.usermodel.IndexedColorMap;
import org.apache.poi.xssf.usermodel.XSSFBuiltinTableStyle; import org.apache.poi.xssf.usermodel.XSSFBuiltinTableStyle;
import org.apache.poi.xssf.usermodel.XSSFCellStyle; import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.apache.poi.xssf.usermodel.XSSFFactory; import org.apache.poi.xssf.usermodel.XSSFFactory;
@ -51,24 +54,7 @@ import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.xssf.usermodel.extensions.XSSFCellBorder; import org.apache.poi.xssf.usermodel.extensions.XSSFCellBorder;
import org.apache.poi.xssf.usermodel.extensions.XSSFCellFill; import org.apache.poi.xssf.usermodel.extensions.XSSFCellFill;
import org.apache.xmlbeans.XmlException; import org.apache.xmlbeans.XmlException;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTBorder; import org.openxmlformats.schemas.spreadsheetml.x2006.main.*;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTBorders;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCellStyleXfs;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCellXfs;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTDxf;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTDxfs;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTFill;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTFills;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTFont;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTFonts;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTNumFmt;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTNumFmts;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTStylesheet;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTTableStyle;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTTableStyles;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTXf;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.STPatternType;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.StyleSheetDocument;
/** /**
* Table of styles shared across all sheets in a workbook. * Table of styles shared across all sheets in a workbook.
@ -84,6 +70,8 @@ public class StylesTable extends POIXMLDocumentPart {
private final List<CTDxf> dxfs = new ArrayList<CTDxf>(); private final List<CTDxf> dxfs = new ArrayList<CTDxf>();
private final Map<String, TableStyle> tableStyles = new HashMap<String, TableStyle>(); private final Map<String, TableStyle> tableStyles = new HashMap<String, TableStyle>();
private IndexedColorMap indexedColors = new DefaultIndexedColorMap();
/** /**
* The first style id available for use as a custom style * The first style id available for use as a custom style
*/ */
@ -170,6 +158,8 @@ public class StylesTable extends POIXMLDocumentPart {
public void setTheme(ThemesTable theme) { public void setTheme(ThemesTable theme) {
this.theme = theme; this.theme = theme;
if (theme != null) theme.setColorMap(getIndexedColors());
// Pass the themes table along to things which need to // Pass the themes table along to things which need to
// know about it, but have already been created by now // know about it, but have already been created by now
for(XSSFFont font : fonts) { for(XSSFFont font : fonts) {
@ -188,7 +178,7 @@ public class StylesTable extends POIXMLDocumentPart {
public void ensureThemesTable() { public void ensureThemesTable() {
if (theme != null) return; if (theme != null) return;
theme = (ThemesTable)workbook.createRelationship(XSSFRelation.THEME, XSSFFactory.getInstance()); setTheme((ThemesTable)workbook.createRelationship(XSSFRelation.THEME, XSSFFactory.getInstance()));
} }
/** /**
@ -204,6 +194,11 @@ public class StylesTable extends POIXMLDocumentPart {
CTStylesheet styleSheet = doc.getStyleSheet(); CTStylesheet styleSheet = doc.getStyleSheet();
// Grab all the different bits we care about // Grab all the different bits we care about
// keep this first, as some constructors below want it
IndexedColorMap customColors = CustomIndexedColorMap.fromColors(styleSheet.getColors());
if (customColors != null) indexedColors = customColors;
CTNumFmts ctfmts = styleSheet.getNumFmts(); CTNumFmts ctfmts = styleSheet.getNumFmts();
if( ctfmts != null){ if( ctfmts != null){
for (CTNumFmt nfmt : ctfmts.getNumFmtArray()) { for (CTNumFmt nfmt : ctfmts.getNumFmtArray()) {
@ -217,7 +212,7 @@ public class StylesTable extends POIXMLDocumentPart {
int idx = 0; int idx = 0;
for (CTFont font : ctfonts.getFontArray()) { for (CTFont font : ctfonts.getFontArray()) {
// Create the font and save it. Themes Table supplied later // Create the font and save it. Themes Table supplied later
XSSFFont f = new XSSFFont(font, idx); XSSFFont f = new XSSFFont(font, idx, indexedColors);
fonts.add(f); fonts.add(f);
idx++; idx++;
} }
@ -225,14 +220,14 @@ public class StylesTable extends POIXMLDocumentPart {
CTFills ctfills = styleSheet.getFills(); CTFills ctfills = styleSheet.getFills();
if(ctfills != null){ if(ctfills != null){
for (CTFill fill : ctfills.getFillArray()) { for (CTFill fill : ctfills.getFillArray()) {
fills.add(new XSSFCellFill(fill)); fills.add(new XSSFCellFill(fill, indexedColors));
} }
} }
CTBorders ctborders = styleSheet.getBorders(); CTBorders ctborders = styleSheet.getBorders();
if(ctborders != null) { if(ctborders != null) {
for (CTBorder border : ctborders.getBorderArray()) { for (CTBorder border : ctborders.getBorderArray()) {
borders.add(new XSSFCellBorder(border)); borders.add(new XSSFCellBorder(border, indexedColors));
} }
} }
@ -249,7 +244,7 @@ public class StylesTable extends POIXMLDocumentPart {
if (ctTableStyles != null) { if (ctTableStyles != null) {
int idx = 0; int idx = 0;
for (CTTableStyle style : Arrays.asList(ctTableStyles.getTableStyleArray())) { for (CTTableStyle style : Arrays.asList(ctTableStyles.getTableStyleArray())) {
tableStyles.put(style.getName(), new XSSFTableStyle(idx, styleDxfs, style)); tableStyles.put(style.getName(), new XSSFTableStyle(idx, styleDxfs, style, indexedColors));
idx++; idx++;
} }
} }
@ -716,8 +711,8 @@ public class StylesTable extends POIXMLDocumentPart {
fonts.add(xssfFont); fonts.add(xssfFont);
CTFill[] ctFill = createDefaultFills(); CTFill[] ctFill = createDefaultFills();
fills.add(new XSSFCellFill(ctFill[0])); fills.add(new XSSFCellFill(ctFill[0], indexedColors));
fills.add(new XSSFCellFill(ctFill[1])); fills.add(new XSSFCellFill(ctFill[1], indexedColors));
CTBorder ctBorder = createDefaultBorder(); CTBorder ctBorder = createDefaultBorder();
borders.add(new XSSFCellBorder(ctBorder)); borders.add(new XSSFCellBorder(ctBorder));
@ -757,7 +752,7 @@ public class StylesTable extends POIXMLDocumentPart {
private static XSSFFont createDefaultFont() { private static XSSFFont createDefaultFont() {
CTFont ctFont = CTFont.Factory.newInstance(); CTFont ctFont = CTFont.Factory.newInstance();
XSSFFont xssfFont=new XSSFFont(ctFont, 0); XSSFFont xssfFont=new XSSFFont(ctFont, 0, null);
xssfFont.setFontHeightInPoints(XSSFFont.DEFAULT_FONT_SIZE); xssfFont.setFontHeightInPoints(XSSFFont.DEFAULT_FONT_SIZE);
xssfFont.setColor(XSSFFont.DEFAULT_FONT_COLOR);//setTheme xssfFont.setColor(XSSFFont.DEFAULT_FONT_COLOR);//setTheme
xssfFont.setFontName(XSSFFont.DEFAULT_FONT_NAME); xssfFont.setFontName(XSSFFont.DEFAULT_FONT_NAME);
@ -881,4 +876,11 @@ public class StylesTable extends POIXMLDocumentPart {
} }
return null; return null;
} }
/**
* @return default or custom indexed color to RGB mapping
*/
public IndexedColorMap getIndexedColors() {
return indexedColors;
}
} }

View File

@ -23,6 +23,7 @@ import java.io.OutputStream;
import org.apache.poi.POIXMLDocumentPart; import org.apache.poi.POIXMLDocumentPart;
import org.apache.poi.openxml4j.opc.PackagePart; import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.xssf.usermodel.IndexedColorMap;
import org.apache.poi.xssf.usermodel.XSSFColor; import org.apache.poi.xssf.usermodel.XSSFColor;
import org.apache.xmlbeans.XmlException; import org.apache.xmlbeans.XmlException;
import org.openxmlformats.schemas.drawingml.x2006.main.CTColor; import org.openxmlformats.schemas.drawingml.x2006.main.CTColor;
@ -60,6 +61,7 @@ public class ThemesTable extends POIXMLDocumentPart {
public final String name; public final String name;
} }
private IndexedColorMap colorMap;
private ThemeDocument theme; private ThemeDocument theme;
/** /**
@ -95,6 +97,14 @@ public class ThemesTable extends POIXMLDocumentPart {
this.theme = theme; this.theme = theme;
} }
/**
* called from {@link StylesTable} when setting theme, used to adjust colors if a custom indexed mapping is defined
* @param colorMap
*/
protected void setColorMap(IndexedColorMap colorMap) {
this.colorMap = colorMap;
}
/** /**
* Convert a theme "index" (as used by fonts etc) into a color. * Convert a theme "index" (as used by fonts etc) into a color.
* @param idx A theme "index" * @param idx A theme "index"
@ -132,7 +142,7 @@ public class ThemesTable extends POIXMLDocumentPart {
} else { } else {
return null; return null;
} }
return new XSSFColor(rgb); return new XSSFColor(rgb, colorMap);
} }
/** /**

View File

@ -0,0 +1,65 @@
/* ====================================================================
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 java.util.List;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTColors;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTRgbColor;
/**
* custom index color map, i.e. from the styles.xml definition
*/
public class CustomIndexedColorMap implements IndexedColorMap {
private final byte[][] colorIndex;
/**
* @param colors array of RGB triplets indexed by color index
*/
private CustomIndexedColorMap(byte [][] colors) {
this.colorIndex = colors;
}
public byte[] getRGB(int index) {
if (colorIndex == null || index < 0 || index >= colorIndex.length) return null;
return colorIndex[index];
}
/**
* OOXML spec says if this exists it must have all indexes.
* <p/>
* From the OOXML Spec, Part 1, section 18.8.27:
* <p/><i>
* This element contains a sequence of RGB color values that correspond to color indexes (zero-based). When
* using the default indexed color palette, the values are not written out, but instead are implied. When the color
* palette has been modified from default, then the entire color palette is written out.
* </i>
* @param colors CTColors from styles.xml possibly defining a custom color indexing scheme
* @return custom indexed color map or null if none defined in the document
*/
public static CustomIndexedColorMap fromColors(CTColors colors) {
if (colors == null || ! colors.isSetIndexedColors()) return null;
List<CTRgbColor> rgbColorList = colors.getIndexedColors().getRgbColorList();
byte[][] customColorIndex = new byte[rgbColorList.size()][3];
for (int i=0; i < rgbColorList.size(); i++) {
customColorIndex[i] = rgbColorList.get(i).getRgb();
}
return new CustomIndexedColorMap(customColorIndex);
}
}

View File

@ -0,0 +1,44 @@
/* ====================================================================
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 org.apache.poi.hssf.util.HSSFColor;
/**
* Uses the legacy colors defined in HSSF for index lookups
*/
public class DefaultIndexedColorMap implements IndexedColorMap {
/**
* @see org.apache.poi.xssf.usermodel.IndexedColorMap#getRGB(int)
*/
public byte[] getRGB(int index) {
return getDefaultRGB(index);
}
/**
* @param index
* @return RGB bytes from HSSF default color by index
*/
public static byte[] getDefaultRGB(int index) {
HSSFColor hssfColor = HSSFColor.getIndexHash().get(index);
if (hssfColor == null) return null;
short[] rgbShort = hssfColor.getTriplet();
return new byte[] {(byte) rgbShort[0], (byte) rgbShort[1], (byte) rgbShort[2]};
}
}

View File

@ -0,0 +1,31 @@
/* ====================================================================
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;
/**
* Interface for color index to RGB mappings.
* May be either the default, built-in mappings
* or custom mappings defined in the document.
*/
public interface IndexedColorMap {
/**
* @param index color index to look up
* @return the RGB array for the index, or null if the index is invalid/undefined
*/
byte[] getRGB(int index);
}

View File

@ -20,19 +20,21 @@ import org.apache.poi.ss.usermodel.BorderFormatting;
import org.apache.poi.ss.usermodel.BorderStyle; import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.Color; import org.apache.poi.ss.usermodel.Color;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTBorder; import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTBorder;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.STBorderStyle;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTBorderPr; import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTBorderPr;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTColor; import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTColor;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.STBorderStyle;
/** /**
* XSSF high level representation for Border Formatting component * XSSF high level representation for Border Formatting component
* of Conditional Formatting settings * of Conditional Formatting settings
*/ */
public class XSSFBorderFormatting implements BorderFormatting { public class XSSFBorderFormatting implements BorderFormatting {
IndexedColorMap _colorMap;
CTBorder _border; CTBorder _border;
/*package*/ XSSFBorderFormatting(CTBorder border) { /*package*/ XSSFBorderFormatting(CTBorder border, IndexedColorMap colorMap) {
_border = border; _border = border;
_colorMap = colorMap;
} }
/** /**
@ -125,7 +127,7 @@ public class XSSFBorderFormatting implements BorderFormatting {
if(!_border.isSetBottom()) return null; if(!_border.isSetBottom()) return null;
CTBorderPr pr = _border.getBottom(); CTBorderPr pr = _border.getBottom();
return new XSSFColor(pr.getColor()); return new XSSFColor(pr.getColor(), _colorMap);
} }
@Override @Override
public short getBottomBorderColor() { public short getBottomBorderColor() {
@ -139,7 +141,7 @@ public class XSSFBorderFormatting implements BorderFormatting {
if(!_border.isSetDiagonal()) return null; if(!_border.isSetDiagonal()) return null;
CTBorderPr pr = _border.getDiagonal(); CTBorderPr pr = _border.getDiagonal();
return new XSSFColor(pr.getColor()); return new XSSFColor(pr.getColor(), _colorMap);
} }
@Override @Override
public short getDiagonalBorderColor() { public short getDiagonalBorderColor() {
@ -153,7 +155,7 @@ public class XSSFBorderFormatting implements BorderFormatting {
if(!_border.isSetLeft()) return null; if(!_border.isSetLeft()) return null;
CTBorderPr pr = _border.getLeft(); CTBorderPr pr = _border.getLeft();
return new XSSFColor(pr.getColor()); return new XSSFColor(pr.getColor(), _colorMap);
} }
@Override @Override
public short getLeftBorderColor() { public short getLeftBorderColor() {
@ -167,7 +169,7 @@ public class XSSFBorderFormatting implements BorderFormatting {
if(!_border.isSetRight()) return null; if(!_border.isSetRight()) return null;
CTBorderPr pr = _border.getRight(); CTBorderPr pr = _border.getRight();
return new XSSFColor(pr.getColor()); return new XSSFColor(pr.getColor(), _colorMap);
} }
@Override @Override
public short getRightBorderColor() { public short getRightBorderColor() {
@ -181,7 +183,7 @@ public class XSSFBorderFormatting implements BorderFormatting {
if(!_border.isSetTop()) return null; if(!_border.isSetTop()) return null;
CTBorderPr pr = _border.getTop(); CTBorderPr pr = _border.getTop();
return new XSSFColor(pr.getColor()); return new XSSFColor(pr.getColor(), _colorMap);
} }
@Override @Override
public short getTopBorderColor() { public short getTopBorderColor() {

View File

@ -204,14 +204,14 @@ public class XSSFCellStyle implements CellStyle {
} }
private void addFill(CTFill fill) { private void addFill(CTFill fill) {
int idx = _stylesSource.putFill(new XSSFCellFill(fill)); int idx = _stylesSource.putFill(new XSSFCellFill(fill,_stylesSource.getIndexedColors()));
_cellXf.setFillId(idx); _cellXf.setFillId(idx);
_cellXf.setApplyFill(true); _cellXf.setApplyFill(true);
} }
private void addBorder(CTBorder border) { private void addBorder(CTBorder border) {
int idx = _stylesSource.putBorder(new XSSFCellBorder(border, _theme)); int idx = _stylesSource.putBorder(new XSSFCellBorder(border, _theme,_stylesSource.getIndexedColors()));
_cellXf.setBorderId(idx); _cellXf.setBorderId(idx);
_cellXf.setApplyBorder(true); _cellXf.setApplyBorder(true);
@ -834,7 +834,7 @@ public class XSSFCellStyle implements CellStyle {
if(border == BorderStyle.NONE) ct.unsetBottom(); if(border == BorderStyle.NONE) ct.unsetBottom();
else pr.setStyle(STBorderStyle.Enum.forInt(border.getCode() + 1)); else pr.setStyle(STBorderStyle.Enum.forInt(border.getCode() + 1));
int idx = _stylesSource.putBorder(new XSSFCellBorder(ct, _theme)); int idx = _stylesSource.putBorder(new XSSFCellBorder(ct, _theme, _stylesSource.getIndexedColors()));
_cellXf.setBorderId(idx); _cellXf.setBorderId(idx);
_cellXf.setApplyBorder(true); _cellXf.setApplyBorder(true);
@ -864,7 +864,7 @@ public class XSSFCellStyle implements CellStyle {
if(border == BorderStyle.NONE) ct.unsetLeft(); if(border == BorderStyle.NONE) ct.unsetLeft();
else pr.setStyle(STBorderStyle.Enum.forInt(border.getCode() + 1)); else pr.setStyle(STBorderStyle.Enum.forInt(border.getCode() + 1));
int idx = _stylesSource.putBorder(new XSSFCellBorder(ct, _theme)); int idx = _stylesSource.putBorder(new XSSFCellBorder(ct, _theme, _stylesSource.getIndexedColors()));
_cellXf.setBorderId(idx); _cellXf.setBorderId(idx);
_cellXf.setApplyBorder(true); _cellXf.setApplyBorder(true);
@ -895,7 +895,7 @@ public class XSSFCellStyle implements CellStyle {
if(border == BorderStyle.NONE) ct.unsetRight(); if(border == BorderStyle.NONE) ct.unsetRight();
else pr.setStyle(STBorderStyle.Enum.forInt(border.getCode() + 1)); else pr.setStyle(STBorderStyle.Enum.forInt(border.getCode() + 1));
int idx = _stylesSource.putBorder(new XSSFCellBorder(ct, _theme)); int idx = _stylesSource.putBorder(new XSSFCellBorder(ct, _theme,_stylesSource.getIndexedColors()));
_cellXf.setBorderId(idx); _cellXf.setBorderId(idx);
_cellXf.setApplyBorder(true); _cellXf.setApplyBorder(true);
@ -926,7 +926,7 @@ public class XSSFCellStyle implements CellStyle {
if(border == BorderStyle.NONE) ct.unsetTop(); if(border == BorderStyle.NONE) ct.unsetTop();
else pr.setStyle(STBorderStyle.Enum.forInt(border.getCode() + 1)); else pr.setStyle(STBorderStyle.Enum.forInt(border.getCode() + 1));
int idx = _stylesSource.putBorder(new XSSFCellBorder(ct, _theme)); int idx = _stylesSource.putBorder(new XSSFCellBorder(ct, _theme,_stylesSource.getIndexedColors()));
_cellXf.setBorderId(idx); _cellXf.setBorderId(idx);
_cellXf.setApplyBorder(true); _cellXf.setApplyBorder(true);
@ -957,7 +957,7 @@ public class XSSFCellStyle implements CellStyle {
if(color != null) pr.setColor(color.getCTColor()); if(color != null) pr.setColor(color.getCTColor());
else pr.unsetColor(); else pr.unsetColor();
int idx = _stylesSource.putBorder(new XSSFCellBorder(ct, _theme)); int idx = _stylesSource.putBorder(new XSSFCellBorder(ct, _theme,_stylesSource.getIndexedColors()));
_cellXf.setBorderId(idx); _cellXf.setBorderId(idx);
_cellXf.setApplyBorder(true); _cellXf.setApplyBorder(true);
@ -1244,7 +1244,7 @@ public class XSSFCellStyle implements CellStyle {
if(color != null) pr.setColor(color.getCTColor()); if(color != null) pr.setColor(color.getCTColor());
else pr.unsetColor(); else pr.unsetColor();
int idx = _stylesSource.putBorder(new XSSFCellBorder(ct, _theme)); int idx = _stylesSource.putBorder(new XSSFCellBorder(ct, _theme,_stylesSource.getIndexedColors()));
_cellXf.setBorderId(idx); _cellXf.setBorderId(idx);
_cellXf.setApplyBorder(true); _cellXf.setApplyBorder(true);
@ -1299,7 +1299,7 @@ public class XSSFCellStyle implements CellStyle {
if(color != null) pr.setColor(color.getCTColor()); if(color != null) pr.setColor(color.getCTColor());
else pr.unsetColor(); else pr.unsetColor();
int idx = _stylesSource.putBorder(new XSSFCellBorder(ct, _theme)); int idx = _stylesSource.putBorder(new XSSFCellBorder(ct, _theme,_stylesSource.getIndexedColors()));
_cellXf.setBorderId(idx); _cellXf.setBorderId(idx);
_cellXf.setApplyBorder(true); _cellXf.setApplyBorder(true);
@ -1356,7 +1356,7 @@ public class XSSFCellStyle implements CellStyle {
if(color != null) pr.setColor(color.getCTColor()); if(color != null) pr.setColor(color.getCTColor());
else pr.unsetColor(); else pr.unsetColor();
int idx = _stylesSource.putBorder(new XSSFCellBorder(ct, _theme)); int idx = _stylesSource.putBorder(new XSSFCellBorder(ct, _theme,_stylesSource.getIndexedColors()));
_cellXf.setBorderId(idx); _cellXf.setBorderId(idx);
_cellXf.setApplyBorder(true); _cellXf.setApplyBorder(true);

View File

@ -22,6 +22,7 @@ import org.apache.poi.ss.usermodel.Color;
import org.apache.poi.ss.usermodel.ExtendedColor; import org.apache.poi.ss.usermodel.ExtendedColor;
import org.apache.poi.ss.usermodel.IndexedColors; import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.util.Internal; import org.apache.poi.util.Internal;
import org.apache.poi.util.Removal;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTColor; import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTColor;
/** /**
@ -29,33 +30,62 @@ import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTColor;
*/ */
public class XSSFColor extends ExtendedColor { public class XSSFColor extends ExtendedColor {
private final CTColor ctColor; private final CTColor ctColor;
private final IndexedColorMap indexedColorMap;
/** /**
* Create an instance of XSSFColor from the supplied XML bean * Create an instance of XSSFColor from the supplied XML bean, with default color indexes
* @param color
* @deprecated 3.17 beta 1 - pass the workbook styles indexed color map, if any
*/ */
@Deprecated
@Removal(version="3.19")
public XSSFColor(CTColor color) { public XSSFColor(CTColor color) {
this.ctColor = color; this(color, new DefaultIndexedColorMap());
} }
/** /**
* Create an new instance of XSSFColor * Create an instance of XSSFColor from the supplied XML bean, with the given color indexes
* @param color
* @param map
*/
public XSSFColor(CTColor color, IndexedColorMap map) {
this.ctColor = color;
this.indexedColorMap = map;
}
/**
* Create an new instance of XSSFColor, without knowledge of any custom indexed colors.
* This is OK for just transiently setting indexes, etc. but is discouraged in read/get uses
*/ */
public XSSFColor() { public XSSFColor() {
this.ctColor = CTColor.Factory.newInstance(); this(CTColor.Factory.newInstance(), null);
} }
/**
* TEST ONLY - does not know about custom indexed colors
* @param clr awt Color
*/
public XSSFColor(java.awt.Color clr) { public XSSFColor(java.awt.Color clr) {
this(); this();
setColor(clr); setColor(clr);
} }
public XSSFColor(byte[] rgb) { /**
this(); *
* @param rgb bytes
* @param colorMap
*/
public XSSFColor(byte[] rgb, IndexedColorMap colorMap) {
this(CTColor.Factory.newInstance(), colorMap);
ctColor.setRgb(rgb); ctColor.setRgb(rgb);
} }
public XSSFColor(IndexedColors indexedColor) { /**
this(); * @param indexedColor color index (Enum named for default colors)
* @param colorMap
*/
public XSSFColor(IndexedColors indexedColor, IndexedColorMap colorMap) {
this(CTColor.Factory.newInstance(), colorMap);
ctColor.setIndexed(indexedColor.index); ctColor.setIndexed(indexedColor.index);
} }
@ -67,7 +97,7 @@ public class XSSFColor extends ExtendedColor {
return ctColor.getAuto(); return ctColor.getAuto();
} }
/** /**
* A boolean value indicating the ctColor is automatic and system ctColor dependent. * @param auto true if the ctColor is automatic and system ctColor dependent.
*/ */
public void setAuto(boolean auto) { public void setAuto(boolean auto) {
ctColor.setAuto(auto); ctColor.setAuto(auto);
@ -82,7 +112,7 @@ public class XSSFColor extends ExtendedColor {
} }
/** /**
* A boolean value indicating the ctColor is RGB or ARGB based * @return true if the ctColor is RGB or ARGB based
*/ */
@Override @Override
public boolean isRGB() { public boolean isRGB() {
@ -90,7 +120,7 @@ public class XSSFColor extends ExtendedColor {
} }
/** /**
* A boolean value indicating the ctColor is Theme based * @return true if the ctColor is Theme based
*/ */
@Override @Override
public boolean isThemed() { public boolean isThemed() {
@ -98,7 +128,7 @@ public class XSSFColor extends ExtendedColor {
} }
/** /**
* A boolean value indicating if the ctColor has a alpha or not * @return true if the ctColor has a alpha
*/ */
public boolean hasAlpha() { public boolean hasAlpha() {
if (! ctColor.isSetRgb()) { if (! ctColor.isSetRgb()) {
@ -108,7 +138,7 @@ public class XSSFColor extends ExtendedColor {
} }
/** /**
* A boolean value indicating if the ctColor has a tint or not * @return true if the ctColor has a tint
*/ */
public boolean hasTint() { public boolean hasTint() {
if (!ctColor.isSetTint()) { if (!ctColor.isSetTint()) {
@ -125,7 +155,7 @@ public class XSSFColor extends ExtendedColor {
return (short)ctColor.getIndexed(); return (short)ctColor.getIndexed();
} }
/** /**
* Indexed ctColor value. Only used for backwards compatibility. References a ctColor in indexedColors. * @return Indexed ctColor value. Only used for backwards compatibility. References a ctColor in indexedColors.
*/ */
public short getIndexed() { public short getIndexed() {
return getIndex(); return getIndex();
@ -133,6 +163,7 @@ public class XSSFColor extends ExtendedColor {
/** /**
* Indexed ctColor value. Only used for backwards compatibility. References a ctColor in indexedColors. * Indexed ctColor value. Only used for backwards compatibility. References a ctColor in indexedColors.
* @param indexed color index
*/ */
public void setIndexed(int indexed) { public void setIndexed(int indexed) {
ctColor.setIndexed(indexed); ctColor.setIndexed(indexed);
@ -185,6 +216,14 @@ public class XSSFColor extends ExtendedColor {
return ctColor.getRgb(); return ctColor.getRgb();
} }
protected byte[] getIndexedRGB() {
if (isIndexed()) {
if (indexedColorMap != null) return indexedColorMap.getRGB(getIndex());
return DefaultIndexedColorMap.getDefaultRGB(getIndex());
}
return null;
}
/** /**
* Standard Alpha Red Green Blue ctColor value (ARGB). * Standard Alpha Red Green Blue ctColor value (ARGB).
*/ */
@ -205,6 +244,7 @@ public class XSSFColor extends ExtendedColor {
/** /**
* Index into the <clrScheme> collection, referencing a particular <sysClr> or * Index into the <clrScheme> collection, referencing a particular <sysClr> or
* <srgbClr> value expressed in the Theme part. * <srgbClr> value expressed in the Theme part.
* @param theme index
*/ */
public void setTheme(int theme) { public void setTheme(int theme) {
ctColor.setTheme(theme); ctColor.setTheme(theme);

View File

@ -30,10 +30,12 @@ import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTColorScale;
* component of Conditional Formatting settings * component of Conditional Formatting settings
*/ */
public class XSSFColorScaleFormatting implements ColorScaleFormatting { public class XSSFColorScaleFormatting implements ColorScaleFormatting {
CTColorScale _scale; private CTColorScale _scale;
private IndexedColorMap _indexedColorMap;
/*package*/ XSSFColorScaleFormatting(CTColorScale scale){ /*package*/ XSSFColorScaleFormatting(CTColorScale scale, IndexedColorMap colorMap){
_scale = scale; _scale = scale;
_indexedColorMap = colorMap;
} }
public int getNumControlPoints() { public int getNumControlPoints() {
@ -54,7 +56,7 @@ public class XSSFColorScaleFormatting implements ColorScaleFormatting {
CTColor[] ctcols = _scale.getColorArray(); CTColor[] ctcols = _scale.getColorArray();
XSSFColor[] c = new XSSFColor[ctcols.length]; XSSFColor[] c = new XSSFColor[ctcols.length];
for (int i=0; i<ctcols.length; i++) { for (int i=0; i<ctcols.length; i++) {
c[i] = new XSSFColor(ctcols[i]); c[i] = new XSSFColor(ctcols[i], _indexedColorMap);
} }
return c; return c;
} }
@ -83,8 +85,11 @@ public class XSSFColorScaleFormatting implements ColorScaleFormatting {
_scale.setCfvoArray(cfvos); _scale.setCfvoArray(cfvos);
} }
/**
* @return color from scale
*/
public XSSFColor createColor() { public XSSFColor createColor() {
return new XSSFColor(_scale.addNewColor()); return new XSSFColor(_scale.addNewColor(), _indexedColorMap);
} }
public XSSFConditionalFormattingThreshold createThreshold() { public XSSFConditionalFormattingThreshold createThreshold() {
return new XSSFConditionalFormattingThreshold(_scale.addNewCfvo()); return new XSSFConditionalFormattingThreshold(_scale.addNewCfvo());

View File

@ -134,7 +134,7 @@ public class XSSFConditionalFormattingRule implements ConditionalFormattingRule
border = dxf.getBorder(); border = dxf.getBorder();
} }
return new XSSFBorderFormatting(border); return new XSSFBorderFormatting(border, _sh.getWorkbook().getStylesSource().getIndexedColors());
} }
/** /**
@ -144,7 +144,7 @@ public class XSSFConditionalFormattingRule implements ConditionalFormattingRule
CTDxf dxf = getDxf(false); CTDxf dxf = getDxf(false);
if(dxf == null || !dxf.isSetBorder()) return null; if(dxf == null || !dxf.isSetBorder()) return null;
return new XSSFBorderFormatting(dxf.getBorder()); return new XSSFBorderFormatting(dxf.getBorder(), _sh.getWorkbook().getStylesSource().getIndexedColors());
} }
/** /**
@ -162,7 +162,7 @@ public class XSSFConditionalFormattingRule implements ConditionalFormattingRule
font = dxf.getFont(); font = dxf.getFont();
} }
return new XSSFFontFormatting(font); return new XSSFFontFormatting(font, _sh.getWorkbook().getStylesSource().getIndexedColors());
} }
/** /**
@ -172,7 +172,7 @@ public class XSSFConditionalFormattingRule implements ConditionalFormattingRule
CTDxf dxf = getDxf(false); CTDxf dxf = getDxf(false);
if(dxf == null || !dxf.isSetFont()) return null; if(dxf == null || !dxf.isSetFont()) return null;
return new XSSFFontFormatting(dxf.getFont()); return new XSSFFontFormatting(dxf.getFont(), _sh.getWorkbook().getStylesSource().getIndexedColors());
} }
/** /**
@ -190,7 +190,7 @@ public class XSSFConditionalFormattingRule implements ConditionalFormattingRule
fill = dxf.getFill(); fill = dxf.getFill();
} }
return new XSSFPatternFormatting(fill); return new XSSFPatternFormatting(fill, _sh.getWorkbook().getStylesSource().getIndexedColors());
} }
/** /**
@ -200,9 +200,14 @@ public class XSSFConditionalFormattingRule implements ConditionalFormattingRule
CTDxf dxf = getDxf(false); CTDxf dxf = getDxf(false);
if(dxf == null || !dxf.isSetFill()) return null; if(dxf == null || !dxf.isSetFill()) return null;
return new XSSFPatternFormatting(dxf.getFill()); return new XSSFPatternFormatting(dxf.getFill(), _sh.getWorkbook().getStylesSource().getIndexedColors());
} }
/**
*
* @param color
* @return data bar formatting
*/
public XSSFDataBarFormatting createDataBarFormatting(XSSFColor color) { public XSSFDataBarFormatting createDataBarFormatting(XSSFColor color) {
// Is it already there? // Is it already there?
if (_cfRule.isSetDataBar() && _cfRule.getType() == STCfType.DATA_BAR) if (_cfRule.isSetDataBar() && _cfRule.getType() == STCfType.DATA_BAR)
@ -228,12 +233,12 @@ public class XSSFConditionalFormattingRule implements ConditionalFormattingRule
max.setType(STCfvoType.Enum.forString(RangeType.MAX.name)); max.setType(STCfvoType.Enum.forString(RangeType.MAX.name));
// Wrap and return // Wrap and return
return new XSSFDataBarFormatting(bar); return new XSSFDataBarFormatting(bar, _sh.getWorkbook().getStylesSource().getIndexedColors());
} }
public XSSFDataBarFormatting getDataBarFormatting() { public XSSFDataBarFormatting getDataBarFormatting() {
if (_cfRule.isSetDataBar()) { if (_cfRule.isSetDataBar()) {
CTDataBar bar = _cfRule.getDataBar(); CTDataBar bar = _cfRule.getDataBar();
return new XSSFDataBarFormatting(bar); return new XSSFDataBarFormatting(bar, _sh.getWorkbook().getStylesSource().getIndexedColors());
} else { } else {
return null; return null;
} }
@ -314,12 +319,12 @@ public class XSSFConditionalFormattingRule implements ConditionalFormattingRule
} }
// Wrap and return // Wrap and return
return new XSSFColorScaleFormatting(scale); return new XSSFColorScaleFormatting(scale, _sh.getWorkbook().getStylesSource().getIndexedColors());
} }
public XSSFColorScaleFormatting getColorScaleFormatting() { public XSSFColorScaleFormatting getColorScaleFormatting() {
if (_cfRule.isSetColorScale()) { if (_cfRule.isSetColorScale()) {
CTColorScale scale = _cfRule.getColorScale(); CTColorScale scale = _cfRule.getColorScale();
return new XSSFColorScaleFormatting(scale); return new XSSFColorScaleFormatting(scale, _sh.getWorkbook().getStylesSource().getIndexedColors());
} else { } else {
return null; return null;
} }

View File

@ -21,6 +21,7 @@ import org.apache.poi.ss.usermodel.CreationHelper;
import org.apache.poi.ss.usermodel.Hyperlink; import org.apache.poi.ss.usermodel.Hyperlink;
import org.apache.poi.util.Internal; import org.apache.poi.util.Internal;
import org.apache.poi.util.Removal; import org.apache.poi.util.Removal;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTColor;
public class XSSFCreationHelper implements CreationHelper { public class XSSFCreationHelper implements CreationHelper {
private final XSSFWorkbook workbook; private final XSSFWorkbook workbook;
@ -52,7 +53,7 @@ public class XSSFCreationHelper implements CreationHelper {
@Override @Override
public XSSFColor createExtendedColor() { public XSSFColor createExtendedColor() {
return new XSSFColor(); return new XSSFColor(CTColor.Factory.newInstance(), workbook.getStylesSource().getIndexedColors());
} }
/** /**

View File

@ -27,10 +27,12 @@ import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTDataBar;
* component of Conditional Formatting settings * component of Conditional Formatting settings
*/ */
public class XSSFDataBarFormatting implements DataBarFormatting { public class XSSFDataBarFormatting implements DataBarFormatting {
IndexedColorMap _colorMap;
CTDataBar _databar; CTDataBar _databar;
/*package*/ XSSFDataBarFormatting(CTDataBar databar){ /*package*/ XSSFDataBarFormatting(CTDataBar databar, IndexedColorMap colorMap){
_databar = databar; _databar = databar;
_colorMap = colorMap;
} }
public boolean isIconOnly() { public boolean isIconOnly() {
@ -64,7 +66,7 @@ public class XSSFDataBarFormatting implements DataBarFormatting {
} }
public XSSFColor getColor() { public XSSFColor getColor() {
return new XSSFColor(_databar.getColor()); return new XSSFColor(_databar.getColor(), _colorMap);
} }
public void setColor(Color color) { public void setColor(Color color) {
_databar.setColor( ((XSSFColor)color).getCTColor() ); _databar.setColor( ((XSSFColor)color).getCTColor() );

View File

@ -30,6 +30,7 @@ import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTNumFmt;
*/ */
public class XSSFDxfStyleProvider implements DifferentialStyleProvider { public class XSSFDxfStyleProvider implements DifferentialStyleProvider {
private final IndexedColorMap colorMap;
private final BorderFormatting border; private final BorderFormatting border;
private final FontFormatting font; private final FontFormatting font;
private final ExcelNumberFormat number; private final ExcelNumberFormat number;
@ -39,24 +40,26 @@ public class XSSFDxfStyleProvider implements DifferentialStyleProvider {
/** /**
* @param dxf * @param dxf
* @param stripeSize 0 for non-stripe styles, > 1 for stripes * @param stripeSize 0 for non-stripe styles, > 1 for stripes
* @param colorMap
*/ */
public XSSFDxfStyleProvider(CTDxf dxf, int stripeSize) { public XSSFDxfStyleProvider(CTDxf dxf, int stripeSize, IndexedColorMap colorMap) {
this.stripeSize = stripeSize; this.stripeSize = stripeSize;
this.colorMap = colorMap;
if (dxf == null) { if (dxf == null) {
border = null; border = null;
font = null; font = null;
number = null; number = null;
fill = null; fill = null;
} else { } else {
border = dxf.isSetBorder() ? new XSSFBorderFormatting(dxf.getBorder()) : null; border = dxf.isSetBorder() ? new XSSFBorderFormatting(dxf.getBorder(), colorMap) : null;
font = dxf.isSetFont() ? new XSSFFontFormatting(dxf.getFont()) : null; font = dxf.isSetFont() ? new XSSFFontFormatting(dxf.getFont(), colorMap) : null;
if (dxf.isSetNumFmt()) { if (dxf.isSetNumFmt()) {
CTNumFmt numFmt = dxf.getNumFmt(); CTNumFmt numFmt = dxf.getNumFmt();
number = new ExcelNumberFormat((int) numFmt.getNumFmtId(), numFmt.getFormatCode()); number = new ExcelNumberFormat((int) numFmt.getNumFmtId(), numFmt.getFormatCode());
} else { } else {
number = null; number = null;
} }
fill = dxf.isSetFill() ? new XSSFPatternFormatting(dxf.getFill()) : null; fill = dxf.isSetFill() ? new XSSFPatternFormatting(dxf.getFill(), colorMap) : null;
} }
} }

View File

@ -60,6 +60,7 @@ public class XSSFFont implements Font {
*/ */
public static final short DEFAULT_FONT_COLOR = IndexedColors.BLACK.getIndex(); public static final short DEFAULT_FONT_COLOR = IndexedColors.BLACK.getIndex();
private IndexedColorMap _indexedColorMap;
private ThemesTable _themes; private ThemesTable _themes;
private CTFont _ctFont; private CTFont _ctFont;
private short _index; private short _index;
@ -74,9 +75,16 @@ public class XSSFFont implements Font {
_index = 0; _index = 0;
} }
public XSSFFont(CTFont font, int index) { /**
* Called from parsing styles.xml
* @param font CTFont
* @param index font index
* @param colorMap for default or custom indexed colors
*/
public XSSFFont(CTFont font, int index, IndexedColorMap colorMap) {
_ctFont = font; _ctFont = font;
_index = (short)index; _index = (short)index;
_indexedColorMap = colorMap;
} }
/** /**
@ -150,7 +158,7 @@ public class XSSFFont implements Font {
public XSSFColor getXSSFColor() { public XSSFColor getXSSFColor() {
CTColor ctColor = _ctFont.sizeOfColorArray() == 0 ? null : _ctFont.getColorArray(0); CTColor ctColor = _ctFont.sizeOfColorArray() == 0 ? null : _ctFont.getColorArray(0);
if(ctColor != null) { if(ctColor != null) {
XSSFColor color = new XSSFColor(ctColor); XSSFColor color = new XSSFColor(ctColor, _indexedColorMap);
if(_themes != null) { if(_themes != null) {
_themes.inheritFromThemeAsRequired(color); _themes.inheritFromThemeAsRequired(color);
} }

View File

@ -33,10 +33,12 @@ import org.openxmlformats.schemas.spreadsheetml.x2006.main.STVerticalAlignRun;
* @author Yegor Kozlov * @author Yegor Kozlov
*/ */
public class XSSFFontFormatting implements FontFormatting { public class XSSFFontFormatting implements FontFormatting {
CTFont _font; private IndexedColorMap _colorMap;
private CTFont _font;
/*package*/ XSSFFontFormatting(CTFont font){ /*package*/ XSSFFontFormatting(CTFont font, IndexedColorMap colorMap) {
_font = font; _font = font;
_colorMap = colorMap;
} }
/** /**
@ -111,7 +113,7 @@ public class XSSFFontFormatting implements FontFormatting {
public XSSFColor getFontColor() { public XSSFColor getFontColor() {
if(_font.sizeOfColorArray() == 0) return null; if(_font.sizeOfColorArray() == 0) return null;
return new XSSFColor(_font.getColorArray(0)); return new XSSFColor(_font.getColorArray(0), _colorMap);
} }
@Override @Override

View File

@ -29,20 +29,22 @@ import org.openxmlformats.schemas.spreadsheetml.x2006.main.STPatternType;
* @author Yegor Kozlov * @author Yegor Kozlov
*/ */
public class XSSFPatternFormatting implements PatternFormatting { public class XSSFPatternFormatting implements PatternFormatting {
IndexedColorMap _colorMap;
CTFill _fill; CTFill _fill;
XSSFPatternFormatting(CTFill fill){ XSSFPatternFormatting(CTFill fill, IndexedColorMap colorMap) {
_fill = fill; _fill = fill;
_colorMap = colorMap;
} }
public XSSFColor getFillBackgroundColorColor() { public XSSFColor getFillBackgroundColorColor() {
if(!_fill.isSetPatternFill()) return null; if(!_fill.isSetPatternFill()) return null;
return new XSSFColor(_fill.getPatternFill().getBgColor()); return new XSSFColor(_fill.getPatternFill().getBgColor(), _colorMap);
} }
public XSSFColor getFillForegroundColorColor() { public XSSFColor getFillForegroundColorColor() {
if(!_fill.isSetPatternFill() || ! _fill.getPatternFill().isSetFgColor()) if(!_fill.isSetPatternFill() || ! _fill.getPatternFill().isSetFgColor())
return null; return null;
return new XSSFColor(_fill.getPatternFill().getFgColor()); return new XSSFColor(_fill.getPatternFill().getFgColor(), _colorMap);
} }
public short getFillPattern() { public short getFillPattern() {

View File

@ -4007,7 +4007,7 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet {
if (!pr.isSetTabColor()) { if (!pr.isSetTabColor()) {
return null; return null;
} }
return new XSSFColor(pr.getTabColor()); return new XSSFColor(pr.getTabColor(), getWorkbook().getStylesSource().getIndexedColors());
} }
/** /**
@ -4020,7 +4020,7 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet {
@Removal(version="3.17") @Removal(version="3.17")
public void setTabColor(int colorIndex) { public void setTabColor(int colorIndex) {
IndexedColors indexedColor = IndexedColors.fromInt(colorIndex); IndexedColors indexedColor = IndexedColors.fromInt(colorIndex);
XSSFColor color = new XSSFColor(indexedColor); XSSFColor color = new XSSFColor(indexedColor, getWorkbook().getStylesSource().getIndexedColors());
setTabColor(color); setTabColor(color);
} }

View File

@ -42,9 +42,10 @@ public class XSSFTableStyle implements TableStyle {
* @param index style definition index or built-in ordinal depending on use * @param index style definition index or built-in ordinal depending on use
* @param dxfs * @param dxfs
* @param tableStyle * @param tableStyle
* @param colorMap indexed color map - default or custom
* @see TableStyle#getIndex() * @see TableStyle#getIndex()
*/ */
public XSSFTableStyle(int index, CTDxfs dxfs, CTTableStyle tableStyle) { public XSSFTableStyle(int index, CTDxfs dxfs, CTTableStyle tableStyle, IndexedColorMap colorMap) {
this.name = tableStyle.getName(); this.name = tableStyle.getName();
this.index = index; this.index = index;
for (CTTableStyleElement element : tableStyle.getTableStyleElementList()) { for (CTTableStyleElement element : tableStyle.getTableStyleElementList()) {
@ -60,7 +61,7 @@ public class XSSFTableStyle implements TableStyle {
} }
int stripeSize = 0; int stripeSize = 0;
if (element.isSetSize()) stripeSize = (int) element.getSize(); if (element.isSetSize()) stripeSize = (int) element.getSize();
if (dxf != null) dstyle = new XSSFDxfStyleProvider(dxf, stripeSize); if (dxf != null) dstyle = new XSSFDxfStyleProvider(dxf, stripeSize, colorMap);
} }
elementMap.put(type, dstyle); elementMap.put(type, dstyle);
} }

View File

@ -19,6 +19,7 @@ package org.apache.poi.xssf.usermodel.extensions;
import org.apache.poi.ss.usermodel.BorderStyle; import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.xssf.model.ThemesTable; import org.apache.poi.xssf.model.ThemesTable;
import org.apache.poi.xssf.usermodel.IndexedColorMap;
import org.apache.poi.xssf.usermodel.XSSFColor; import org.apache.poi.xssf.usermodel.XSSFColor;
import org.apache.poi.util.Internal; import org.apache.poi.util.Internal;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTBorder; import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTBorder;
@ -31,22 +32,37 @@ import org.openxmlformats.schemas.spreadsheetml.x2006.main.STBorderStyle;
* Color is optional. * Color is optional.
*/ */
public class XSSFCellBorder { public class XSSFCellBorder {
private IndexedColorMap _indexedColorMap;
private ThemesTable _theme; private ThemesTable _theme;
private CTBorder border; private CTBorder border;
/** /**
* Creates a Cell Border from the supplied XML definition * Creates a Cell Border from the supplied XML definition
* @param border
* @param theme
* @param colorMap
*/ */
public XSSFCellBorder(CTBorder border, ThemesTable theme) { public XSSFCellBorder(CTBorder border, ThemesTable theme, IndexedColorMap colorMap) {
this(border); this(border, colorMap);
this._theme = theme; this._theme = theme;
} }
/** /**
* Creates a Cell Border from the supplied XML definition * Creates a Cell Border from the supplied XML definition
* @param border
*/ */
public XSSFCellBorder(CTBorder border) { public XSSFCellBorder(CTBorder border) {
this(border, null);
}
/**
*
* @param border
* @param colorMap
*/
public XSSFCellBorder(CTBorder border, IndexedColorMap colorMap) {
this.border = border; this.border = border;
this._indexedColorMap = colorMap;
} }
/** /**
@ -117,7 +133,7 @@ public class XSSFCellBorder {
CTBorderPr borderPr = getBorder(side); CTBorderPr borderPr = getBorder(side);
if(borderPr != null && borderPr.isSetColor()) { if(borderPr != null && borderPr.isSetColor()) {
XSSFColor clr = new XSSFColor(borderPr.getColor()); XSSFColor clr = new XSSFColor(borderPr.getColor(), _indexedColorMap);
if(_theme != null) { if(_theme != null) {
_theme.inheritFromThemeAsRequired(clr); _theme.inheritFromThemeAsRequired(clr);
} }

View File

@ -20,6 +20,7 @@ import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTColor;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTFill; import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTFill;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTPatternFill; import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTPatternFill;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.STPatternType; import org.openxmlformats.schemas.spreadsheetml.x2006.main.STPatternType;
import org.apache.poi.xssf.usermodel.IndexedColorMap;
import org.apache.poi.xssf.usermodel.XSSFColor; import org.apache.poi.xssf.usermodel.XSSFColor;
import org.apache.poi.util.Internal; import org.apache.poi.util.Internal;
@ -29,6 +30,7 @@ import org.apache.poi.util.Internal;
*/ */
public final class XSSFCellFill { public final class XSSFCellFill {
private IndexedColorMap _indexedColorMap;
private CTFill _fill; private CTFill _fill;
/** /**
@ -36,8 +38,9 @@ public final class XSSFCellFill {
* *
* @param fill - fill * @param fill - fill
*/ */
public XSSFCellFill(CTFill fill) { public XSSFCellFill(CTFill fill, IndexedColorMap colorMap) {
_fill = fill; _fill = fill;
_indexedColorMap = colorMap;
} }
/** /**
@ -57,7 +60,7 @@ public final class XSSFCellFill {
if (ptrn == null) return null; if (ptrn == null) return null;
CTColor ctColor = ptrn.getBgColor(); CTColor ctColor = ptrn.getBgColor();
return ctColor == null ? null : new XSSFColor(ctColor); return ctColor == null ? null : new XSSFColor(ctColor, _indexedColorMap);
} }
/** /**
@ -91,7 +94,7 @@ public final class XSSFCellFill {
if (ptrn == null) return null; if (ptrn == null) return null;
CTColor ctColor = ptrn.getFgColor(); CTColor ctColor = ptrn.getFgColor();
return ctColor == null ? null : new XSSFColor(ctColor); return ctColor == null ? null : new XSSFColor(ctColor, _indexedColorMap);
} }
/** /**

View File

@ -73,7 +73,7 @@ public class TestXSSFCellStyle {
assertEquals(1, stylesTable.putBorder(borderB)); assertEquals(1, stylesTable.putBorder(borderB));
ctFill = CTFill.Factory.newInstance(); ctFill = CTFill.Factory.newInstance();
XSSFCellFill fill = new XSSFCellFill(ctFill); XSSFCellFill fill = new XSSFCellFill(ctFill, null);
long fillId = stylesTable.putFill(fill); long fillId = stylesTable.putFill(fill);
assertEquals(2, fillId); assertEquals(2, fillId);

View File

@ -17,12 +17,16 @@
package org.apache.poi.xssf.usermodel; package org.apache.poi.xssf.usermodel;
import static org.junit.Assert.*; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.io.IOException; import java.io.IOException;
import org.apache.poi.xssf.XSSFTestDataSamples; import org.apache.poi.xssf.XSSFTestDataSamples;
import org.junit.Test; import org.junit.Test;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTColors;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTRgbColor;
public final class TestXSSFColor { public final class TestXSSFColor {
@ -180,4 +184,21 @@ public final class TestXSSFColor {
wb.close(); wb.close();
} }
@Test
public void testCustomIndexedColour() throws Exception {
XSSFWorkbook wb = XSSFTestDataSamples.openSampleWorkbook("customIndexedColors.xlsx");
XSSFCell cell = wb.getSheetAt(1).getRow(0).getCell(0);
XSSFColor color = cell.getCellStyle().getFillForegroundColorColor();
CTColors ctColors = wb.getStylesSource().getCTStylesheet().getColors();
CTRgbColor ctRgbColor = ctColors.getIndexedColors()
.getRgbColorList()
.get(color.getIndex());
String hexRgb = ctRgbColor.getDomNode().getAttributes().getNamedItem("rgb").getNodeValue();
assertEquals(hexRgb, color.getARGBHex());
}
} }

View File

@ -256,7 +256,7 @@ public final class TestXSSFFont extends BaseTestFont{
byte[] bytes = Integer.toHexString(0xF1F1F1).getBytes(LocaleUtil.CHARSET_1252); byte[] bytes = Integer.toHexString(0xF1F1F1).getBytes(LocaleUtil.CHARSET_1252);
color.setRgb(bytes); color.setRgb(bytes);
XSSFColor newColor=new XSSFColor(color); XSSFColor newColor=new XSSFColor(color, null);
xssfFont.setColor(newColor); xssfFont.setColor(newColor);
assertEquals(ctFont.getColorArray(0).getRgb()[2],newColor.getRGB()[2]); assertEquals(ctFont.getColorArray(0).getRgb()[2],newColor.getRGB()[2]);

View File

@ -1892,7 +1892,7 @@ public final class TestXSSFSheet extends BaseTestXSheet {
try { try {
XSSFSheet sh = wb.createSheet(); XSSFSheet sh = wb.createSheet();
assertTrue(sh.getCTWorksheet().getSheetPr() == null || !sh.getCTWorksheet().getSheetPr().isSetTabColor()); assertTrue(sh.getCTWorksheet().getSheetPr() == null || !sh.getCTWorksheet().getSheetPr().isSetTabColor());
sh.setTabColor(new XSSFColor(IndexedColors.RED)); sh.setTabColor(new XSSFColor(IndexedColors.RED, null));
assertTrue(sh.getCTWorksheet().getSheetPr().isSetTabColor()); assertTrue(sh.getCTWorksheet().getSheetPr().isSetTabColor());
assertEquals(IndexedColors.RED.index, assertEquals(IndexedColors.RED.index,
sh.getCTWorksheet().getSheetPr().getTabColor().getIndexed()); sh.getCTWorksheet().getSheetPr().getTabColor().getIndexed());
@ -1908,8 +1908,8 @@ public final class TestXSSFSheet extends BaseTestXSheet {
XSSFSheet sh = wb.createSheet(); XSSFSheet sh = wb.createSheet();
assertTrue(sh.getCTWorksheet().getSheetPr() == null || !sh.getCTWorksheet().getSheetPr().isSetTabColor()); assertTrue(sh.getCTWorksheet().getSheetPr() == null || !sh.getCTWorksheet().getSheetPr().isSetTabColor());
assertNull(sh.getTabColor()); assertNull(sh.getTabColor());
sh.setTabColor(new XSSFColor(IndexedColors.RED)); sh.setTabColor(new XSSFColor(IndexedColors.RED, null));
XSSFColor expected = new XSSFColor(IndexedColors.RED); XSSFColor expected = new XSSFColor(IndexedColors.RED, null);
assertEquals(expected, sh.getTabColor()); assertEquals(expected, sh.getTabColor());
} finally { } finally {
wb.close(); wb.close();
@ -1925,7 +1925,7 @@ public final class TestXSSFSheet extends BaseTestXSheet {
assertNull(wb.getSheet("default").getTabColor()); assertNull(wb.getSheet("default").getTabColor());
// test indexed-colored sheet // test indexed-colored sheet
XSSFColor expected = new XSSFColor(IndexedColors.RED); XSSFColor expected = new XSSFColor(IndexedColors.RED, null);
assertEquals(expected, wb.getSheet("indexedRed").getTabColor()); assertEquals(expected, wb.getSheet("indexedRed").getTabColor());
// test regular-colored (non-indexed, ARGB) sheet // test regular-colored (non-indexed, ARGB) sheet

View File

@ -40,7 +40,7 @@ public class TestXSSFCellFill {
@Test @Test
public void testGetFillBackgroundColor() { public void testGetFillBackgroundColor() {
CTFill ctFill = CTFill.Factory.newInstance(); CTFill ctFill = CTFill.Factory.newInstance();
XSSFCellFill cellFill = new XSSFCellFill(ctFill); XSSFCellFill cellFill = new XSSFCellFill(ctFill, null);
CTPatternFill ctPatternFill = ctFill.addNewPatternFill(); CTPatternFill ctPatternFill = ctFill.addNewPatternFill();
CTColor bgColor = ctPatternFill.addNewBgColor(); CTColor bgColor = ctPatternFill.addNewBgColor();
assertNotNull(cellFill.getFillBackgroundColor()); assertNotNull(cellFill.getFillBackgroundColor());
@ -51,7 +51,7 @@ public class TestXSSFCellFill {
@Test @Test
public void testGetFillForegroundColor() { public void testGetFillForegroundColor() {
CTFill ctFill = CTFill.Factory.newInstance(); CTFill ctFill = CTFill.Factory.newInstance();
XSSFCellFill cellFill = new XSSFCellFill(ctFill); XSSFCellFill cellFill = new XSSFCellFill(ctFill, null);
CTPatternFill ctPatternFill = ctFill.addNewPatternFill(); CTPatternFill ctPatternFill = ctFill.addNewPatternFill();
CTColor fgColor = ctPatternFill.addNewFgColor(); CTColor fgColor = ctPatternFill.addNewFgColor();
assertNotNull(cellFill.getFillForegroundColor()); assertNotNull(cellFill.getFillForegroundColor());
@ -62,7 +62,7 @@ public class TestXSSFCellFill {
@Test @Test
public void testGetSetPatternType() { public void testGetSetPatternType() {
CTFill ctFill = CTFill.Factory.newInstance(); CTFill ctFill = CTFill.Factory.newInstance();
XSSFCellFill cellFill = new XSSFCellFill(ctFill); XSSFCellFill cellFill = new XSSFCellFill(ctFill, null);
CTPatternFill ctPatternFill = ctFill.addNewPatternFill(); CTPatternFill ctPatternFill = ctFill.addNewPatternFill();
ctPatternFill.setPatternType(STPatternType.SOLID); ctPatternFill.setPatternType(STPatternType.SOLID);
assertEquals(FillPatternType.SOLID_FOREGROUND.ordinal(), cellFill.getPatternType().intValue()-1); assertEquals(FillPatternType.SOLID_FOREGROUND.ordinal(), cellFill.getPatternType().intValue()-1);
@ -71,7 +71,7 @@ public class TestXSSFCellFill {
@Test @Test
public void testGetNotModifies() { public void testGetNotModifies() {
CTFill ctFill = CTFill.Factory.newInstance(); CTFill ctFill = CTFill.Factory.newInstance();
XSSFCellFill cellFill = new XSSFCellFill(ctFill); XSSFCellFill cellFill = new XSSFCellFill(ctFill, null);
CTPatternFill ctPatternFill = ctFill.addNewPatternFill(); CTPatternFill ctPatternFill = ctFill.addNewPatternFill();
ctPatternFill.setPatternType(STPatternType.DARK_DOWN); ctPatternFill.setPatternType(STPatternType.DARK_DOWN);
assertEquals(8, cellFill.getPatternType().intValue()); assertEquals(8, cellFill.getPatternType().intValue());

Binary file not shown.