297 lines
11 KiB
Java
297 lines
11 KiB
Java
/* ====================================================================
|
|
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.ddf;
|
|
|
|
import org.apache.poi.util.BitField;
|
|
import org.apache.poi.util.LittleEndian;
|
|
|
|
/**
|
|
* An OfficeArtCOLORREF structure entry which also handles color extension opid data
|
|
*/
|
|
public class EscherColorRef {
|
|
@SuppressWarnings("unused")
|
|
private int opid = -1;
|
|
private int colorRef = 0;
|
|
|
|
public enum SysIndexSource {
|
|
/** Use the fill color of the shape. */
|
|
FILL_COLOR(0xF0),
|
|
/** If the shape contains a line, use the line color of the shape. Otherwise, use the fill color. */
|
|
LINE_OR_FILL_COLOR(0xF1),
|
|
/** Use the line color of the shape. */
|
|
LINE_COLOR(0xF2),
|
|
/** Use the shadow color of the shape. */
|
|
SHADOW_COLOR(0xF3),
|
|
/** Use the current, or last-used, color. */
|
|
CURRENT_OR_LAST_COLOR(0xF4),
|
|
/** Use the fill background color of the shape. */
|
|
FILL_BACKGROUND_COLOR(0xF5),
|
|
/** Use the line background color of the shape. */
|
|
LINE_BACKGROUND_COLOR(0xF6),
|
|
/** If the shape contains a fill, use the fill color of the shape. Otherwise, use the line color. */
|
|
FILL_OR_LINE_COLOR(0xF7)
|
|
;
|
|
private int value;
|
|
SysIndexSource(int value) { this.value = value; }
|
|
}
|
|
|
|
/**
|
|
* The following enum specifies values that indicate special procedural properties that
|
|
* are used to modify the color components of another color. These values are combined with
|
|
* those of the {@link SysIndexSource} enum or with a user-specified color.
|
|
* The first six values are mutually exclusive.
|
|
*/
|
|
public enum SysIndexProcedure {
|
|
/**
|
|
* Darken the color by the value that is specified in the blue field.
|
|
* A blue value of 0xFF specifies that the color is to be left unchanged,
|
|
* whereas a blue value of 0x00 specifies that the color is to be completely darkened.
|
|
*/
|
|
DARKEN_COLOR(0x01),
|
|
/**
|
|
* Lighten the color by the value that is specified in the blue field.
|
|
* A blue value of 0xFF specifies that the color is to be left unchanged,
|
|
* whereas a blue value of 0x00 specifies that the color is to be completely lightened.
|
|
*/
|
|
LIGHTEN_COLOR(0x02),
|
|
/**
|
|
* Add a gray level RGB value. The blue field contains the gray level to add:
|
|
* NewColor = SourceColor + gray
|
|
*/
|
|
ADD_GRAY_LEVEL(0x03),
|
|
/**
|
|
* Subtract a gray level RGB value. The blue field contains the gray level to subtract:
|
|
* NewColor = SourceColor - gray
|
|
*/
|
|
SUB_GRAY_LEVEL(0x04),
|
|
/**
|
|
* Reverse-subtract a gray level RGB value. The blue field contains the gray level from
|
|
* which to subtract:
|
|
* NewColor = gray - SourceColor
|
|
*/
|
|
REVERSE_GRAY_LEVEL(0x05),
|
|
/**
|
|
* If the color component being modified is less than the parameter contained in the blue
|
|
* field, set it to the minimum intensity. If the color component being modified is greater
|
|
* than or equal to the parameter, set it to the maximum intensity.
|
|
*/
|
|
THRESHOLD(0x06),
|
|
/**
|
|
* After making other modifications, invert the color.
|
|
* This enum value is only for documentation and won't be directly returned.
|
|
*/
|
|
INVERT_AFTER(0x20),
|
|
/**
|
|
* After making other modifications, invert the color by toggling just the high bit of each
|
|
* color channel.
|
|
* This enum value is only for documentation and won't be directly returned.
|
|
*/
|
|
INVERT_HIGHBIT_AFTER(0x40)
|
|
;
|
|
private BitField mask;
|
|
SysIndexProcedure(int mask) {
|
|
this.mask = new BitField(mask);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* A bit that specifies whether the system color scheme will be used to determine the color.
|
|
* A value of 0x1 specifies that green and red will be treated as an unsigned 16-bit index
|
|
* into the system color table. Values less than 0x00F0 map directly to system colors.
|
|
*/
|
|
private static final BitField FLAG_SYS_INDEX = new BitField(0x10000000);
|
|
|
|
/**
|
|
* A bit that specifies whether the current application-defined color scheme will be used
|
|
* to determine the color. A value of 0x1 specifies that red will be treated as an index
|
|
* into the current color scheme table. If this value is 0x1, green and blue MUST be 0x00.
|
|
*/
|
|
private static final BitField FLAG_SCHEME_INDEX = new BitField(0x08000000);
|
|
|
|
/**
|
|
* A bit that specifies whether the color is a standard RGB color.
|
|
* 0x0 : The RGB color MAY use halftone dithering to display.
|
|
* 0x1 : The color MUST be a solid color.
|
|
*/
|
|
private static final BitField FLAG_SYSTEM_RGB = new BitField(0x04000000);
|
|
|
|
/**
|
|
* A bit that specifies whether the current palette will be used to determine the color.
|
|
* A value of 0x1 specifies that red, green, and blue contain an RGB value that will be
|
|
* matched in the current color palette. This color MUST be solid.
|
|
*/
|
|
private static final BitField FLAG_PALETTE_RGB = new BitField(0x02000000);
|
|
|
|
/**
|
|
* A bit that specifies whether the current palette will be used to determine the color.
|
|
* A value of 0x1 specifies that green and red will be treated as an unsigned 16-bit index into
|
|
* the current color palette. This color MAY be dithered. If this value is 0x1, blue MUST be 0x00.
|
|
*/
|
|
private static final BitField FLAG_PALETTE_INDEX = new BitField(0x01000000);
|
|
|
|
/**
|
|
* An unsigned integer that specifies the intensity of the blue color channel. A value
|
|
* of 0x00 has the minimum blue intensity. A value of 0xFF has the maximum blue intensity.
|
|
*/
|
|
private static final BitField FLAG_BLUE = new BitField(0x00FF0000);
|
|
|
|
/**
|
|
* An unsigned integer that specifies the intensity of the green color channel. A value
|
|
* of 0x00 has the minimum green intensity. A value of 0xFF has the maximum green intensity.
|
|
*/
|
|
private static final BitField FLAG_GREEN = new BitField(0x0000FF00);
|
|
|
|
/**
|
|
* An unsigned integer that specifies the intensity of the red color channel. A value
|
|
* of 0x00 has the minimum red intensity. A value of 0xFF has the maximum red intensity.
|
|
*/
|
|
private static final BitField FLAG_RED = new BitField(0x000000FF);
|
|
|
|
public EscherColorRef(int colorRef) {
|
|
this.colorRef = colorRef;
|
|
}
|
|
|
|
public EscherColorRef(byte[] source, int start, int len) {
|
|
assert(len == 4 || len == 6);
|
|
|
|
int offset = start;
|
|
if (len == 6) {
|
|
opid = LittleEndian.getUShort(source, offset);
|
|
offset += 2;
|
|
}
|
|
colorRef = LittleEndian.getInt(source, offset);
|
|
}
|
|
|
|
public boolean hasSysIndexFlag() {
|
|
return FLAG_SYS_INDEX.isSet(colorRef);
|
|
}
|
|
|
|
public void setSysIndexFlag(boolean flag) {
|
|
colorRef = FLAG_SYS_INDEX.setBoolean(colorRef, flag);
|
|
}
|
|
|
|
public boolean hasSchemeIndexFlag() {
|
|
return FLAG_SCHEME_INDEX.isSet(colorRef);
|
|
}
|
|
|
|
public void setSchemeIndexFlag(boolean flag) {
|
|
colorRef = FLAG_SCHEME_INDEX.setBoolean(colorRef, flag);
|
|
}
|
|
|
|
public boolean hasSystemRGBFlag() {
|
|
return FLAG_SYSTEM_RGB.isSet(colorRef);
|
|
}
|
|
|
|
public void setSystemRGBFlag(boolean flag) {
|
|
colorRef = FLAG_SYSTEM_RGB.setBoolean(colorRef, flag);
|
|
}
|
|
|
|
public boolean hasPaletteRGBFlag() {
|
|
return FLAG_PALETTE_RGB.isSet(colorRef);
|
|
}
|
|
|
|
public void setPaletteRGBFlag(boolean flag) {
|
|
colorRef = FLAG_PALETTE_RGB.setBoolean(colorRef, flag);
|
|
}
|
|
|
|
public boolean hasPaletteIndexFlag() {
|
|
return FLAG_PALETTE_INDEX.isSet(colorRef);
|
|
}
|
|
|
|
public void setPaletteIndexFlag(boolean flag) {
|
|
colorRef = FLAG_PALETTE_INDEX.setBoolean(colorRef, flag);
|
|
}
|
|
|
|
public int[] getRGB() {
|
|
int rgb[] = {
|
|
FLAG_RED.getValue(colorRef),
|
|
FLAG_GREEN.getValue(colorRef),
|
|
FLAG_BLUE.getValue(colorRef)
|
|
};
|
|
return rgb;
|
|
}
|
|
|
|
/**
|
|
* @return {@link SysIndexSource} if {@link #hasSysIndexFlag()} is {@code true}, otherwise null
|
|
*/
|
|
public SysIndexSource getSysIndexSource() {
|
|
if (!hasSysIndexFlag()) return null;
|
|
int val = FLAG_RED.getValue(colorRef);
|
|
for (SysIndexSource sis : SysIndexSource.values()) {
|
|
if (sis.value == val) return sis;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Return the {@link SysIndexProcedure} - for invert flag use {@link #getSysIndexInvert()}
|
|
* @return {@link SysIndexProcedure} if {@link #hasSysIndexFlag()} is {@code true}, otherwise null
|
|
*/
|
|
public SysIndexProcedure getSysIndexProcedure() {
|
|
if (!hasSysIndexFlag()) return null;
|
|
int val = FLAG_GREEN.getValue(colorRef);
|
|
for (SysIndexProcedure sip : SysIndexProcedure.values()) {
|
|
if (sip == SysIndexProcedure.INVERT_AFTER || sip == SysIndexProcedure.INVERT_HIGHBIT_AFTER) continue;
|
|
if (sip.mask.isSet(val)) return sip;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* @return 0 for no invert flag, 1 for {@link SysIndexProcedure#INVERT_AFTER} and
|
|
* 2 for {@link SysIndexProcedure#INVERT_HIGHBIT_AFTER}
|
|
*/
|
|
public int getSysIndexInvert() {
|
|
if (!hasSysIndexFlag()) return 0;
|
|
int val = FLAG_GREEN.getValue(colorRef);
|
|
if ((SysIndexProcedure.INVERT_AFTER.mask.isSet(val))) return 1;
|
|
if ((SysIndexProcedure.INVERT_HIGHBIT_AFTER.mask.isSet(val))) return 2;
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* @return index of the scheme color or -1 if {@link #hasSchemeIndexFlag()} is {@code false}
|
|
*
|
|
* @see org.apache.poi.hslf.record.ColorSchemeAtom#getColor(int)
|
|
*/
|
|
public int getSchemeIndex() {
|
|
if (!hasSchemeIndexFlag()) return -1;
|
|
return FLAG_RED.getValue(colorRef);
|
|
}
|
|
|
|
/**
|
|
* @return index of current palette (color) or -1 if {@link #hasPaletteIndexFlag()} is {@code false}
|
|
*/
|
|
public int getPaletteIndex() {
|
|
return (hasPaletteIndexFlag()) ? getIndex() : -1;
|
|
}
|
|
|
|
/**
|
|
* @return index of system color table or -1 if {@link #hasSysIndexFlag()} is {@code false}
|
|
*
|
|
* @see org.apache.poi.sl.usermodel.PresetColor
|
|
*/
|
|
public int getSysIndex() {
|
|
return (hasSysIndexFlag()) ? getIndex() : -1;
|
|
}
|
|
|
|
private int getIndex() {
|
|
return (FLAG_GREEN.getValue(colorRef) << 8) | FLAG_RED.getValue(colorRef);
|
|
}
|
|
}
|