123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199 |
- /* ====================================================================
- 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.hssf.record;
-
- import java.util.ArrayList;
- import java.util.Arrays;
- import java.util.Map;
- import java.util.function.Supplier;
-
- import org.apache.poi.common.usermodel.GenericRecord;
- import org.apache.poi.util.GenericRecordUtil;
- import org.apache.poi.util.LittleEndianOutput;
-
- /**
- * Supports custom palettes.
- */
- public final class PaletteRecord extends StandardRecord {
- public static final short sid = 0x0092;
- /** The standard size of an XLS palette */
- public static final byte STANDARD_PALETTE_SIZE = (byte) 56;
- /** The byte index of the first color */
- public static final short FIRST_COLOR_INDEX = (short) 0x8;
-
- private static final int[] DEFAULT_COLORS = {
- 0x000000, 0xFFFFFF, 0xFF0000, 0x00FF00, 0x0000FF, 0xFFFF00, 0xFF00FF, 0x00FFFF,
- 0x800000, 0x008000, 0x000080, 0x808000, 0x800080, 0x008080, 0xC0C0C0, 0x808080,
- 0x9999FF, 0x993366, 0xFFFFCC, 0xCCFFFF, 0x660066, 0xFF8080, 0x0066CC, 0xCCCCFF,
- 0x000080, 0xFF00FF, 0xFFFF00, 0x00FFFF, 0x800080, 0x800000, 0x008080, 0x0000FF,
- 0x00CCFF, 0xCCFFFF, 0xCCFFCC, 0xFFFF99, 0x99CCFF, 0xFF99CC, 0xCC99FF, 0xFFCC99,
- 0x3366FF, 0x33CCCC, 0x99CC00, 0xFFCC00, 0xFF9900, 0xFF6600, 0x666699, 0x969696,
- 0x003366, 0x339966, 0x003300, 0x333300, 0x993300, 0x993366, 0x333399, 0x333333
- };
-
- private final ArrayList<PColor> _colors = new ArrayList<>(100);
-
- public PaletteRecord() {
- Arrays.stream(DEFAULT_COLORS).mapToObj(PColor::new).forEach(_colors::add);
- }
-
- public PaletteRecord(PaletteRecord other) {
- super(other);
- _colors.ensureCapacity(other._colors.size());
- other._colors.stream().map(PColor::new).forEach(_colors::add);
- }
-
- public PaletteRecord(RecordInputStream in) {
- int field_1_numcolors = in.readShort();
- _colors.ensureCapacity(field_1_numcolors);
- for (int k = 0; k < field_1_numcolors; k++) {
- _colors.add(new PColor(in));
- }
- }
-
- @Override
- public void serialize(LittleEndianOutput out) {
- out.writeShort(_colors.size());
- for (PColor color : _colors) {
- color.serialize(out);
- }
- }
-
- @Override
- protected int getDataSize() {
- return 2 + _colors.size() * PColor.ENCODED_SIZE;
- }
-
- @Override
- public short getSid() {
- return sid;
- }
-
- /**
- * Returns the color value at a given index
- *
- * @param byteIndex palette index, must be >= 0x8
- *
- * @return the RGB triplet for the color, or <code>null</code> if the specified index
- * does not exist
- */
- public byte[] getColor(int byteIndex) {
- int i = byteIndex - FIRST_COLOR_INDEX;
- if (i < 0 || i >= _colors.size()) {
- return null;
- }
- return _colors.get(i).getTriplet();
- }
-
- /**
- * Sets the color value at a given index
- *
- * If the given index is greater than the current last color index,
- * then black is inserted at every index required to make the palette continuous.
- *
- * @param byteIndex the index to set; if this index is less than 0x8 or greater than
- * 0x40, then no modification is made
- * @param red the red color part
- * @param green the green color part
- * @param blue the blue color part
- */
- public void setColor(short byteIndex, byte red, byte green, byte blue)
- {
- int i = byteIndex - FIRST_COLOR_INDEX;
- if (i < 0 || i >= STANDARD_PALETTE_SIZE)
- {
- return;
- }
- // may need to grow - fill intervening palette entries with black
- while (_colors.size() <= i) {
- _colors.add(new PColor(0, 0, 0));
- }
- PColor custColor = new PColor(red, green, blue);
- _colors.set(i, custColor);
- }
-
- @Override
- public PaletteRecord copy() {
- return new PaletteRecord(this);
- }
-
- @Override
- public HSSFRecordTypes getGenericRecordType() {
- return HSSFRecordTypes.PALETTE;
- }
-
- @Override
- public Map<String, Supplier<?>> getGenericProperties() {
- return GenericRecordUtil.getGenericProperties("colors", () -> _colors);
- }
-
- /**
- * PColor - element in the list of colors
- */
- private static final class PColor implements GenericRecord {
- public static final short ENCODED_SIZE = 4;
- private final int _red;
- private final int _green;
- private final int _blue;
-
- PColor(int rgb) {
- _red = (rgb >>> 16) & 0xFF;
- _green = (rgb >>> 8) & 0xFF;
- _blue = rgb & 0xFF;
- }
-
- PColor(int red, int green, int blue) {
- _red = red;
- _green = green;
- _blue = blue;
- }
-
- PColor(PColor other) {
- _red = other._red;
- _green = other._green;
- _blue = other._blue;
- }
-
- PColor(RecordInputStream in) {
- _red = in.readByte();
- _green = in.readByte();
- _blue = in.readByte();
- in.readByte(); // unused
- }
-
- byte[] getTriplet() {
- return new byte[] { (byte) _red, (byte) _green, (byte) _blue };
- }
-
- void serialize(LittleEndianOutput out) {
- out.writeByte(_red);
- out.writeByte(_green);
- out.writeByte(_blue);
- out.writeByte(0);
- }
-
- @Override
- public Map<String, Supplier<?>> getGenericProperties() {
- return GenericRecordUtil.getGenericProperties(
- "red", () -> _red & 0xFF,
- "green", () -> _green & 0xFF,
- "blue", () -> _blue & 0xFF
- );
- }
- }
- }
|