123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429 |
- /* ====================================================================
- 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.Arrays;
-
- import org.apache.poi.ss.usermodel.Color;
- import org.apache.poi.ss.usermodel.ExtendedColor;
- import org.apache.poi.ss.usermodel.IndexedColors;
- import org.apache.poi.util.Internal;
- import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTColor;
-
- /**
- * Represents a color in SpreadsheetML
- */
- public class XSSFColor extends ExtendedColor {
- private final CTColor ctColor;
- private final IndexedColorMap indexedColorMap;
-
- /**
- * @param color The ooxml color object to use
- * @param map The IndexedColorMap to use instead of the default one (can be null)
- * @return null if color is null, new instance otherwise
- */
- public static XSSFColor from(CTColor color, IndexedColorMap map) {
- return color == null ? null : new XSSFColor(color, map);
- }
-
- /**
- * @param color The ooxml color object to use
- * @return null if color is null, new instance otherwise
- * @since POI 5.2.0
- */
- public static XSSFColor from(CTColor color) {
- return color == null ? null : new XSSFColor(color, null);
- }
-
- private XSSFColor(CTColor color, IndexedColorMap map) {
- this.ctColor = color;
- this.indexedColorMap = map;
- }
-
- /**
- * @since POI 5.2.0
- */
- public XSSFColor() {
- this(CTColor.Factory.newInstance(), null);
- }
-
- /**
- * new color with the given indexed color map
- * @param colorMap The IndexedColorMap to use instead of the default one (can be null)
- */
- public XSSFColor(IndexedColorMap colorMap) {
- this(CTColor.Factory.newInstance(), colorMap);
- }
-
- /**
- * TEST ONLY
- * @param clr awt Color
- * @param map The IndexedColorMap to use instead of the default one (can be null)
- */
- public XSSFColor(java.awt.Color clr, IndexedColorMap map) {
- this(map);
- setColor(clr);
- }
-
- /**
- * @param rgb The RGB-byte-values for the Color
- * @param colorMap The IndexedColorMap to use instead of the default one (can be null)
- */
- public XSSFColor(byte[] rgb, IndexedColorMap colorMap) {
- this(CTColor.Factory.newInstance(), colorMap);
- ctColor.setRgb(rgb);
- }
-
- /**
- * @param rgb The RGB-byte-values for the Color
- * @since POI 5.2.0
- */
- public XSSFColor(byte[] rgb) {
- this(rgb, null);
- }
-
- /**
- * @param indexedColor color index (Enum named for default colors)
- * @param colorMap The IndexedColorMap to use instead of the default one
- */
- public XSSFColor(IndexedColors indexedColor, IndexedColorMap colorMap) {
- this(CTColor.Factory.newInstance(), colorMap);
- ctColor.setIndexed(indexedColor.index);
- }
-
- /**
- * A boolean value indicating the ctColor is automatic and system ctColor dependent.
- */
- @Override
- public boolean isAuto() {
- return ctColor.getAuto();
- }
-
- /**
- * @param auto true if the ctColor is automatic and system ctColor dependent.
- */
- public void setAuto(boolean auto) {
- ctColor.setAuto(auto);
- }
-
- /**
- * A boolean value indicating the ctColor is Indexed
- */
- @Override
- public boolean isIndexed() {
- return ctColor.isSetIndexed();
- }
-
- /**
- * @return true if the ctColor is RGB or ARGB based
- */
- @Override
- public boolean isRGB() {
- return ctColor.isSetRgb();
- }
-
- /**
- * @return true if the ctColor is Theme based
- */
- @Override
- public boolean isThemed() {
- return ctColor.isSetTheme();
- }
-
- /**
- * @return true if the ctColor has a alpha
- */
- public boolean hasAlpha() {
- return ctColor.isSetRgb() && ctColor.getRgb().length == 4;
- }
-
- /**
- * @return true if the ctColor has a tint
- */
- public boolean hasTint() {
- return ctColor.isSetTint() && ctColor.getTint() != 0;
- }
-
- /**
- * Indexed ctColor value. Only used for backwards compatibility. References a ctColor in indexedColors.
- */
- @Override
- public short getIndex() {
- return (short)ctColor.getIndexed();
- }
- /**
- * @return Indexed ctColor value. Only used for backwards compatibility. References a ctColor in indexedColors.
- */
- public short getIndexed() {
- return getIndex();
- }
-
- /**
- * Indexed ctColor value. Only used for backwards compatibility. References a ctColor in indexedColors.
- * @param indexed color index
- */
- public void setIndexed(int indexed) {
- ctColor.setIndexed(indexed);
- }
-
- /**
- * Standard Red Green Blue ctColor value (RGB).
- * If there was an A (Alpha) value, it will be stripped.
- */
- @Override
- public byte[] getRGB() {
- byte[] rgb = getRGBOrARGB();
- if(rgb == null) {
- return null;
- }
-
- // Need to trim off the alpha
- return rgb.length == 4 ? Arrays.copyOfRange(rgb, 1, 4) : rgb;
- }
-
- /**
- * Standard Alpha Red Green Blue ctColor value (ARGB).
- */
- @Override
- 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;
- }
- }
-
- @Override
- protected byte[] getStoredRBG() {
- return ctColor.getRgb();
- }
-
- @Override
- 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).
- */
- @Override
- public void setRGB(byte[] rgb) {
- ctColor.setRgb(rgb);
- }
-
- /**
- * Index into the {@code clrScheme} collection, referencing a particular {@code sysClr} or
- * {@code srgbClr} value expressed in the Theme part.
- */
- @Override
- public int getTheme() {
- return (int)ctColor.getTheme();
- }
-
- /**
- * Index into the {@code clrScheme} collection, referencing a particular {@code sysClr} or
- * {@code srgbClr} value expressed in the Theme part.
- * @param theme index
- */
- public void setTheme(int theme) {
- ctColor.setTheme(theme);
- }
-
- /**
- * 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 < 0)
- * Lum' = Lum * (1.0 + tint)
- *
- * For example: Lum = 200; tint = -0.5; Darken 50%
- * Lum' = 200 * (0.5) => 100
- * For example: Lum = 200; tint = -1.0; Darken 100% (make black)
- * Lum' = 200 * (1.0-1.0) => 0
- * If (tint > 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
- */
- @Override
- public double getTint() {
- return ctColor.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 < 0)
- * Lum' = Lum * (1.0 + tint)
- *
- * For example: Lum = 200; tint = -0.5; Darken 50%
- * Lum' = 200 * (0.5) => 100
- * For example: Lum = 200; tint = -1.0; Darken 100% (make black)
- * Lum' = 200 * (1.0-1.0) => 0
- * If (tint > 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
- */
- @Override
- public void setTint(double tint) {
- ctColor.setTint(tint);
- }
-
- /**
- * Returns the underlying XML bean
- *
- * @return the underlying XML bean
- */
- @Internal
- public CTColor getCTColor(){
- return ctColor;
- }
-
- /**
- * Checked type cast {@code color} to an XSSFColor.
- *
- * @param color the color to type cast
- * @return the type casted color
- * @throws IllegalArgumentException if color is null or is not an instance of XSSFColor
- */
- public static XSSFColor toXSSFColor(Color color) {
- // FIXME: this method would be more useful if it could convert any Color to an XSSFColor
- // Currently the only benefit of this method is to throw an IllegalArgumentException
- // instead of a ClassCastException.
- if (color != null && !(color instanceof XSSFColor)) {
- throw new IllegalArgumentException("Only XSSFColor objects are supported, but had " + color.getClass());
- }
- return (XSSFColor)color;
- }
-
- @Override
- public int hashCode(){
- return ctColor.toString().hashCode();
- }
-
- // Helper methods for {@link #equals(Object)}
- private boolean sameIndexed(XSSFColor other) {
- if (isIndexed() == other.isIndexed()) {
- return !isIndexed() || getIndexed() == other.getIndexed();
- }
- return false;
- }
- private boolean sameARGB(XSSFColor other) {
- if (isRGB() == other.isRGB()) {
- return !isRGB() || Arrays.equals(getARGB(), other.getARGB());
- }
- return false;
- }
- private boolean sameTheme(XSSFColor other) {
- if (isThemed() == other.isThemed()) {
- return !isThemed() || getTheme() == other.getTheme();
- }
- return false;
- }
- private boolean sameTint(XSSFColor other) {
- if (hasTint() == other.hasTint()) {
- return !hasTint() || getTint() == other.getTint();
- }
- return false;
- }
- private boolean sameAuto(XSSFColor other) {
- return isAuto() == other.isAuto();
- }
-
- @Override
- public boolean equals(Object o){
- if(!(o instanceof XSSFColor)) {
- return false;
- }
-
- XSSFColor other = (XSSFColor)o;
-
- // Compare each field in ctColor.
- // Cannot compare ctColor's XML string representation because equivalent
- // colors may have different relation namespace URI's
- return sameARGB(other)
- && sameTheme(other)
- && sameIndexed(other)
- && sameTint(other)
- && sameAuto(other);
- }
- }
|