001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: /* $Id: RtfColorTable.java 426576 2006-07-28 15:44:37Z jeremias $ */
019:
020: package org.apache.fop.render.rtf.rtflib.rtfdoc;
021:
022: /*
023: * This file is part of the RTF library of the FOP project, which was originally
024: * created by Bertrand Delacretaz <bdelacretaz@codeconsult.ch> and by other
025: * contributors to the jfor project (www.jfor.org), who agreed to donate jfor to
026: * the FOP project.
027: */
028:
029: import java.util.Vector;
030: import java.util.Hashtable;
031: import java.io.IOException;
032:
033: /**
034: * Singelton of the RTF color table.
035: * This class was created for <fo:basic-link> tag processing.
036: * @author <a href="mailto:a.putz@skynamics.com">Andreas Putz</a>
037: */
038:
039: public final class RtfColorTable {
040: //////////////////////////////////////////////////
041: // @@ Symbolic constants
042: //////////////////////////////////////////////////
043:
044: // Defines the bit moving for the colors
045: private static final int RED = 16;
046: private static final int GREEN = 8;
047: private static final int BLUE = 0;
048:
049: //////////////////////////////////////////////////
050: // @@ Members
051: //////////////////////////////////////////////////
052:
053: /** Singelton instance */
054: private static RtfColorTable instance = null;
055:
056: /** Index table for the colors */
057: private Hashtable colorIndex = null;
058: /** Used colors to this vector */
059: private Vector colorTable = null;
060: /** Map of color names to color numbers */
061: private Hashtable namedColors = null;
062:
063: //////////////////////////////////////////////////
064: // @@ Construction
065: //////////////////////////////////////////////////
066:
067: /**
068: * Constructor.
069: */
070: private RtfColorTable() {
071: colorTable = new Vector();
072: colorIndex = new Hashtable();
073: namedColors = new Hashtable();
074:
075: init();
076: }
077:
078: /**
079: * Singelton.
080: *
081: * @return The instance of RTFColorTable
082: */
083: public static RtfColorTable getInstance() {
084: if (instance == null) {
085: instance = new RtfColorTable();
086: }
087:
088: return instance;
089: }
090:
091: //////////////////////////////////////////////////
092: // @@ Initializing
093: //////////////////////////////////////////////////
094:
095: /**
096: * Initialize the color table.
097: */
098: private void init() {
099: addNamedColor("black", getColorNumber(0, 0, 0).intValue());
100: addNamedColor("white", getColorNumber(255, 255, 255).intValue());
101: addNamedColor("red", getColorNumber(255, 0, 0).intValue());
102: addNamedColor("green", getColorNumber(0, 255, 0).intValue());
103: addNamedColor("blue", getColorNumber(0, 0, 255).intValue());
104: addNamedColor("cyan", getColorNumber(0, 255, 255).intValue());
105: addNamedColor("magenta", getColorNumber(255, 0, 255).intValue());
106: addNamedColor("yellow", getColorNumber(255, 255, 0).intValue());
107:
108: getColorNumber(0, 0, 128);
109: getColorNumber(0, 128, 128);
110: getColorNumber(0, 128, 0);
111: getColorNumber(128, 0, 128);
112: getColorNumber(128, 0, 0);
113: getColorNumber(128, 128, 0);
114: getColorNumber(128, 128, 128);
115:
116: // Added by Normand Masse
117: // Gray color added
118: addNamedColor("gray", getColorNumber(128, 128, 128).intValue());
119:
120: getColorNumber(192, 192, 192);
121: }
122:
123: /** define a named color for getColorNumber(String) */
124: private void addNamedColor(String name, int colorNumber) {
125: namedColors.put(name.toLowerCase(), new Integer(colorNumber));
126: }
127:
128: //////////////////////////////////////////////////
129: // @@ Public methods
130: //////////////////////////////////////////////////
131:
132: /**
133: * @param name a named color
134: * @return the RTF number of a named color, or null if name not found
135: */
136: public Integer getColorNumber(String name) {
137: return ((Integer) namedColors.get(name.toLowerCase()));
138: }
139:
140: /**
141: * Gets the number of color in the color table
142: *
143: * @param red Color level red
144: * @param green Color level green
145: * @param blue Color level blue
146: *
147: * @return The number of the color in the table
148: */
149: public Integer getColorNumber(int red, int green, int blue) {
150: Integer identifier = new Integer(determineIdentifier(red,
151: green, blue));
152: Object o = colorIndex.get(identifier);
153: int retVal;
154:
155: if (o == null) {
156: //The color currently does not exist, so add it to the table.
157: //First add it, then read the size as index (to return it).
158: //So the first added color gets index 1. That is OK, because
159: //index 0 is reserved for auto-colored.
160: addColor(identifier);
161:
162: retVal = colorTable.size();
163: } else {
164: //The color was found. Before returning the index, increment
165: //it by one. Because index 0 is reserved for auto-colored, but
166: //is not contained in colorTable.
167: retVal = ((Integer) o).intValue() + 1;
168: }
169:
170: return new Integer(retVal);
171: }
172:
173: /**
174: * Writes the color table in the header.
175: *
176: * @param header The header container to write in
177: *
178: * @throws IOException On error
179: */
180: public void writeColors(RtfHeader header) throws IOException {
181: if (colorTable == null || colorTable.size() == 0) {
182: return;
183: }
184:
185: header.newLine();
186: header.writeGroupMark(true);
187: //Don't use writeControlWord, because it appends a blank,
188: //which may confuse Wordpad.
189: //This also implicitly writes the first color (=index 0), which
190: //is reserved for auto-colored.
191: header.write("\\colortbl;");
192:
193: int len = colorTable.size();
194:
195: for (int i = 0; i < len; i++) {
196: int identifier = ((Integer) colorTable.get(i)).intValue();
197:
198: header.newLine();
199: header
200: .write("\\red"
201: + determineColorLevel(identifier, RED));
202: header.write("\\green"
203: + determineColorLevel(identifier, GREEN));
204: header.write("\\blue"
205: + determineColorLevel(identifier, BLUE) + ";");
206: }
207:
208: header.newLine();
209: header.writeGroupMark(false);
210: }
211:
212: //////////////////////////////////////////////////
213: // @@ Private methods
214: //////////////////////////////////////////////////
215:
216: /**
217: * Adds a color to the table.
218: *
219: * @param i Identifier of color
220: */
221: private void addColor(Integer i) {
222: colorIndex.put(i, new Integer(colorTable.size()));
223: colorTable.addElement(i);
224: }
225:
226: /**
227: * Determines a identifier for the color.
228: *
229: * @param red Color level red
230: * @param green Color level green
231: * @param blue Color level blue
232: *
233: * @return Unique identifier of color
234: */
235: private int determineIdentifier(int red, int green, int blue) {
236: int c = red << RED;
237:
238: c += green << GREEN;
239: c += blue << BLUE;
240:
241: return c;
242: }
243:
244: /**
245: * Determines the color level from the identifier.
246: *
247: * @param identifier Unique color identifier
248: * @param color One of the bit moving constants
249: *
250: * @return Color level in byte size
251: */
252: private int determineColorLevel(int identifier, int color) {
253: int retVal = (byte) (identifier >> color);
254:
255: return retVal < 0 ? retVal + 256 : retVal;
256: }
257: }
|