Move some of the XSSF Color logic to a base class, so that the HSSF Extended Color wrapper can use it

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1691864 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Nick Burch 2015-07-20 00:46:50 +00:00
parent ca1dfbd1e5
commit d788ff06b4
2 changed files with 296 additions and 74 deletions

View File

@ -0,0 +1,237 @@
/* ====================================================================
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.ss.usermodel;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.usermodel.Color;
/**
* Represents a XSSF-style color (based on either a
* {@link org.apache.poi.xssf.usermodel.XSSFColor} or a
* {@link org.apache.poi.hssf.record.common.ExtendedColor}
*/
public abstract class ExtendedColor implements Color {
protected void setColor(java.awt.Color clr) {
setRGB(new byte[]{(byte)clr.getRed(), (byte)clr.getGreen(), (byte)clr.getBlue()});
}
/**
* A boolean value indicating the color is automatic
*/
public abstract boolean isAuto();
/**
* A boolean value indicating the color is indexed
*/
public abstract boolean isIndexed();
/**
* A boolean value indicating the color is RGB / ARGB
*/
public abstract boolean isRGB();
/**
* A boolean value indicating the color is from a Theme
*/
public abstract boolean isThemed();
/**
* Indexed Color value, if {@link #isIndexed()} is true
*/
public abstract short getIndex();
/**
* Index of Theme color, if {@link #isThemed()} is true
*/
public abstract int getTheme();
/**
* Standard Red Green Blue ctColor value (RGB).
* If there was an A (Alpha) value, it will be stripped.
*/
public abstract byte[] getRGB();
/**
* Standard Alpha Red Green Blue ctColor value (ARGB).
*/
public abstract byte[] getARGB();
/**
* RGB or ARGB or null
*/
protected abstract byte[] getStoredRBG();
/**
* Sets the Red Green Blue or Alpha Red Green Blue
*/
public abstract void setRGB(byte[] rgb);
protected byte[] getRGBOrARGB() {
byte[] rgb = null;
if (isIndexed() && getIndex() > 0) {
int indexNum = getIndex();
HSSFColor indexed = HSSFColor.getIndexHash().get(indexNum);
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;
}
}
// Grab the colour
rgb = getStoredRBG();
return rgb;
}
/**
* Standard Red Green Blue ctColor value (RGB) with applied tint.
* Alpha values are ignored.
*/
public byte[] getRGBWithTint() {
byte[] rgb = getStoredRBG();
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, 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 = getARGB();
if(rgb == null) {
return null;
}
for(byte c : rgb) {
int i = c & 0xff;
String cs = Integer.toHexString(i);
if(cs.length() == 1) {
sb.append('0');
}
sb.append(cs);
}
return sb.toString().toUpperCase();
}
private static byte applyTint(int lum, double tint){
if(tint > 0){
return (byte)(lum * (1.0-tint) + (255 - 255 * (1.0-tint)));
} else if (tint < 0){
return (byte)(lum*(1+tint));
} else {
return (byte)lum;
}
}
/**
* Specifies the tint value applied to the ctColor.
*
* <p>
* If tint is supplied, then it is applied to the RGB value of the ctColor to determine the final
* ctColor applied.
* </p>
* <p>
* The tint value is stored as a double from -1.0 .. 1.0, where -1.0 means 100% darken and
* 1.0 means 100% lighten. Also, 0.0 means no change.
* </p>
* <p>
* In loading the RGB value, it is converted to HLS where HLS values are (0..HLSMAX), where
* HLSMAX is currently 255.
* </p>
* Here are some examples of how to apply tint to ctColor:
* <blockquote>
* <pre>
* If (tint &lt; 0)
* Lum' = Lum * (1.0 + tint)
*
* For example: Lum = 200; tint = -0.5; Darken 50%
* Lum' = 200 * (0.5) =&gt; 100
* For example: Lum = 200; tint = -1.0; Darken 100% (make black)
* Lum' = 200 * (1.0-1.0) =&gt; 0
* If (tint &gt; 0)
* Lum' = Lum * (1.0-tint) + (HLSMAX - HLSMAX * (1.0-tint))
* For example: Lum = 100; tint = 0.75; Lighten 75%
*
* Lum' = 100 * (1-.75) + (HLSMAX - HLSMAX*(1-.75))
* = 100 * .25 + (255 - 255 * .25)
* = 25 + (255 - 63) = 25 + 192 = 217
* For example: Lum = 100; tint = 1.0; Lighten 100% (make white)
* Lum' = 100 * (1-1) + (HLSMAX - HLSMAX*(1-1))
* = 100 * 0 + (255 - 255 * 0)
* = 0 + (255 - 0) = 255
* </pre>
* </blockquote>
*
* @return the tint value
*/
public abstract double getTint();
/**
* Specifies the tint value applied to the ctColor.
*
* <p>
* If tint is supplied, then it is applied to the RGB value of the ctColor to determine the final
* ctColor applied.
* </p>
* <p>
* The tint value is stored as a double from -1.0 .. 1.0, where -1.0 means 100% darken and
* 1.0 means 100% lighten. Also, 0.0 means no change.
* </p>
* <p>
* In loading the RGB value, it is converted to HLS where HLS values are (0..HLSMAX), where
* HLSMAX is currently 255.
* </p>
* Here are some examples of how to apply tint to ctColor:
* <blockquote>
* <pre>
* If (tint &lt; 0)
* Lum' = Lum * (1.0 + tint)
*
* For example: Lum = 200; tint = -0.5; Darken 50%
* Lum' = 200 * (0.5) =&gt; 100
* For example: Lum = 200; tint = -1.0; Darken 100% (make black)
* Lum' = 200 * (1.0-1.0) =&gt; 0
* If (tint &gt; 0)
* Lum' = Lum * (1.0-tint) + (HLSMAX - HLSMAX * (1.0-tint))
* For example: Lum = 100; tint = 0.75; Lighten 75%
*
* Lum' = 100 * (1-.75) + (HLSMAX - HLSMAX*(1-.75))
* = 100 * .25 + (255 - 255 * .25)
* = 25 + (255 - 63) = 25 + 192 = 217
* For example: Lum = 100; tint = 1.0; Lighten 100% (make white)
* Lum' = 100 * (1-1) + (HLSMAX - HLSMAX*(1-1))
* = 100 * 0 + (255 - 255 * 0)
* = 0 + (255 - 0) = 255
* </pre>
* </blockquote>
*
* @param tint the tint value
*/
public abstract void setTint(double tint);
}

View File

@ -16,16 +16,15 @@
==================================================================== */
package org.apache.poi.xssf.usermodel;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.usermodel.Color;
import org.apache.poi.ss.usermodel.ExtendedColor;
import org.apache.poi.util.Internal;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTColor;
/**
* Represents a color in SpreadsheetML
*/
public class XSSFColor implements Color {
public class XSSFColor extends ExtendedColor {
private CTColor ctColor;
/**
@ -44,7 +43,7 @@ public class XSSFColor implements Color {
public XSSFColor(java.awt.Color clr) {
this();
ctColor.setRgb(new byte[]{(byte)clr.getRed(), (byte)clr.getGreen(), (byte)clr.getBlue()});
setColor(clr);
}
public XSSFColor(byte[] rgb) {
@ -55,10 +54,10 @@ public class XSSFColor implements Color {
/**
* A boolean value indicating the ctColor is automatic and system ctColor dependent.
*/
@Override
public boolean isAuto() {
return ctColor.getAuto();
}
/**
* A boolean value indicating the ctColor is automatic and system ctColor dependent.
*/
@ -66,11 +65,41 @@ public class XSSFColor implements Color {
ctColor.setAuto(auto);
}
/**
* A boolean value indicating the ctColor is Indexed
*/
@Override
public boolean isIndexed() {
return ctColor.isSetIndexed();
}
/**
* A boolean value indicating the ctColor is RGB or ARGB based
*/
@Override
public boolean isRGB() {
return ctColor.isSetRgb();
}
/**
* A boolean value indicating the ctColor is Theme based
*/
@Override
public boolean isThemed() {
return ctColor.isSetTheme();
}
/**
* Indexed ctColor value. Only used for backwards compatibility. References a ctColor in indexedColors.
*/
public short getIndex() {
return (short)ctColor.getIndexed();
}
/**
* Indexed ctColor value. Only used for backwards compatibility. References a ctColor in indexedColors.
*/
public short getIndexed() {
return (short)ctColor.getIndexed();
return getIndex();
}
/**
@ -84,7 +113,7 @@ public class XSSFColor implements Color {
* Standard Red Green Blue ctColor value (RGB).
* If there was an A (Alpha) value, it will be stripped.
*/
public byte[] getRgb() {
public byte[] getRGB() {
byte[] rgb = getRGBOrARGB();
if(rgb == null) return null;
@ -97,11 +126,17 @@ public class XSSFColor implements Color {
return rgb;
}
}
/**
* @deprecated use {@link #getRGB()}
*/
public byte[] getRgb() {
return getRGB();
}
/**
* Standard Alpha Red Green Blue ctColor value (ARGB).
*/
public byte[] getARgb() {
public byte[] getARGB() {
byte[] rgb = getRGBOrARGB();
if(rgb == null) return null;
@ -115,85 +150,35 @@ public class XSSFColor implements Color {
return rgb;
}
}
/**
* @deprecated Use {@link #getARGB()}
*/
public byte[] getARgb() {
return getARGB();
}
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();
return rgb;
}
protected byte[] getStoredRBG() {
return ctColor.getRgb();
}
/**
* Standard Red Green Blue ctColor value (RGB) with applied tint.
* Alpha values are ignored.
*/
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;
}
/**
* 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 = getARgb();
if(rgb == null) {
return null;
}
for(byte c : rgb) {
int i = c & 0xff;
String cs = Integer.toHexString(i);
if(cs.length() == 1) {
sb.append('0');
}
sb.append(cs);
}
return sb.toString().toUpperCase();
}
private static byte applyTint(int lum, double tint){
if(tint > 0){
return (byte)(lum * (1.0-tint) + (255 - 255 * (1.0-tint)));
} else if (tint < 0){
return (byte)(lum*(1+tint));
} else {
return (byte)lum;
}
return getRGBWithTint();
}
/**
* Standard Alpha Red Green Blue ctColor value (ARGB).
*/
public void setRgb(byte[] rgb) {
setRGB(rgb);
}
/**
* Standard Alpha Red Green Blue ctColor value (ARGB).
*/
public void setRGB(byte[] rgb) {
ctColor.setRgb(rgb);
}