1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 package org.openoffice.xmerge.converter.xml.sxw.wordsmith;
25 
26 import java.io.IOException;
27 import java.awt.Color;
28 
29 import org.w3c.dom.NodeList;
30 import org.w3c.dom.Node;
31 import org.w3c.dom.NamedNodeMap;
32 import org.w3c.dom.Element;
33 
34 import org.openoffice.xmerge.Document;
35 import org.openoffice.xmerge.ConverterCapabilities;
36 import org.openoffice.xmerge.converter.xml.OfficeDocument;
37 import org.openoffice.xmerge.converter.xml.sxw.SxwDocument;
38 import org.openoffice.xmerge.converter.xml.*;
39 
40 /**
41  *  This class represents a color table in a WordSmith document.
42  *
43  *  @author   David Proulx
44  */
45 class WseColorTable extends Wse {
46 
47     private Color fgColors[];
48     private Color bgColors[];
49 
50     /**
51      *  Constructor to use when going from DOM to WordSmith
52      */
WseColorTable()53     public WseColorTable() {
54         fgColors = new Color[16];
55         bgColors = new Color[16];
56 
57         // Always need these two!
58         fgColors[0] = Color.black;
59         bgColors[0] = Color.white;
60 
61     }
62 
63     /**
64      *  Constructor to use when going from WordSmith to DOM.
65      *
66      *  @param  dataArray  <code>byte</code> array.
67      *  @param  i          The index.
68      */
WseColorTable(byte dataArray[], int i)69     public WseColorTable(byte dataArray[], int i) {
70         fgColors = new Color[16];
71         bgColors = new Color[16];
72 
73         i += 2;  // Skip leading "64" and table length field.
74         for (int k = 0; k < 16; k++) {
75             fgColors[k] = new Color(((int)dataArray[i+1]) & 0xFF,
76                                     ((int)dataArray[i+2]) & 0xFF,
77                                     ((int)dataArray[i+3]) & 0xFF);
78             i += 4;
79         }
80         for (int k = 0; k < 16; k++) {
81             bgColors[k] = new Color(((int)dataArray[i+1]) & 0xFF,
82                                     ((int)dataArray[i+2]) & 0xFF,
83                                     ((int)dataArray[i+3]) & 0xFF);
84             i += 4;
85        }
86 
87     }
88 
89 
90     /**
91      *  Compute the index of the first <code>byte</code> following the
92      *  paragraph descriptor, assuming that
93      *  <code>dataArray[startIndex]</code> is the beginning of a valid
94      *  paragraph descriptor.
95      *
96      *  @param dataArray   <code>byte</code array.
97      *  @param startIndex  The start index.
98      *
99      *  @return   The index of the first <code>byte</code> following the
100      *            paragraph description.
101      */
computeNewIndex(byte dataArray[], int startIndex)102     static int computeNewIndex(byte dataArray[], int startIndex) {
103         int tableLen = dataArray[startIndex + 1];
104         tableLen &= 0xFF;  // eliminate problems with sign-extension
105         return startIndex + tableLen + 2;
106     }
107 
108 
109     /**
110      *  Return true if <code>dataArray[startIndex]</code> is the start
111      *  of a valid paragraph descriptor.
112      *
113      *  @param dataArray   <code>byte</code> array.
114      *  @param startIndex  Start index.
115      *
116      *  @return  true if <code>dataArray[startIndex]</code> is the start
117      *           of a valid paragraph descriptor, false otherwise.
118      */
isValid(byte dataArray[], int startIndex)119     static boolean isValid(byte dataArray[], int startIndex) {
120         try {
121             if (dataArray[startIndex] != 64)
122                 return false;
123             int len = dataArray[startIndex + 1];
124             len &= 0xFF;  // eliminate problems with sign-extension
125             int temp = dataArray[startIndex + (int)len + 2];  // probe end of table
126         } catch (ArrayIndexOutOfBoundsException e) {
127             return false;
128         }
129         return true;
130     }
131 
132 
133     /**
134      *  Return the number of bytes needed to represent this color table.
135      *
136      *  @return  The byte count.
137      */
getByteCount()138     int getByteCount() {
139     return (32 * 4) + 1 + 1;
140     }
141 
142 
143     /**
144      *  Return a <code>byte</code> array representing this color table.
145      *
146      *  @return  <code>bytes</code> array representing this color table.
147      */
getBytes()148     byte[] getBytes() {
149         byte[] b = new byte[(32 * 4) + 1 + 1];
150         b[0] = 0x40;
151         b[1] = (byte)128;
152         int i = 2;
153         // int indVal = 0xd8;
154         int indVal = 0;
155 
156         for (int j = 0; j < 16; j++) {
157             b[i++] = (byte)indVal++;
158             if (fgColors[j] != null) {
159                 b[i++] = (byte)fgColors[j].getRed();
160                 b[i++] = (byte)fgColors[j].getGreen();
161                 b[i++] = (byte)fgColors[j].getBlue();
162             } else {
163                 b[i++] = (byte)0;
164                 b[i++] = (byte)0;
165                 b[i++] = (byte)0;
166             }
167         }
168 
169         for (int j = 0; j < 16; j++) {
170             b[i++] = (byte)indVal++;
171             if (bgColors[j] != null) {
172                 b[i++] = (byte)bgColors[j].getRed();
173                 b[i++] = (byte)bgColors[j].getGreen();
174                 b[i++] = (byte)bgColors[j].getBlue();
175             } else {
176                 b[i++] = (byte)0xFF;
177                 b[i++] = (byte)0xFF;
178                 b[i++] = (byte)0xFF;
179             }
180         }
181 
182         return b;
183     }
184 
185 
186     /**
187      *  Return the index of the specified foreground or background
188      *  <code>Color</code>.  (If the color is not already in the table,
189      *  it will be added.)
190      *
191      *  Note that the implementation of this may include a "margin of
192      *  error" to prevent the color table from being filled up too
193      *  quickly.
194      *
195      *  @param c           The <code>Color</code>.
196      *  @param foreground  true if foreground color, false if background
197      *                    color
198      *
199      *  @return  The index of the specified foreground or background
200      *          <code>Color</code>.
201      *
202      *  DJP: how to handle table overflow?
203      */
findColor(Color c, boolean foreground)204     int findColor(Color c, boolean foreground) {
205 
206         Color colorArray[] = foreground ? fgColors : bgColors;
207 
208         for (int i = 0; i < 16; i++) {
209             if (colorArray[i] != null) {
210                 if (colorArray[i].equals(c))
211                     return i;
212             }
213             else
214                 break;  // hit a null entry - no more colors in table!
215         }
216 
217         // Color was not found in the table.  Add it.
218         for (int i = 0; i < 16; i++) {
219             if (colorArray[i] == null) {
220                 colorArray[i] = c;
221                 return i;
222             }
223         }
224         return 0;  // Default - we should never get here though.
225     }
226 
227 
228     /**
229      *  Given an index, return the <code>Color</code> from the table.
230      *
231      *  @param index       The index
232      *  @param foreground  true if foreground color, false if background
233      *                     color
234      *
235      *  @return            The <code>Color</code> at the specified index.
236      */
getColor(int index, boolean foreground)237     Color getColor(int index, boolean foreground) {
238 
239         Color colorArray[] = foreground ? fgColors : bgColors;
240         return colorArray[index];
241     }
242 }
243 
244