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 
28 import org.w3c.dom.Node;
29 import org.w3c.dom.NamedNodeMap;
30 import org.w3c.dom.Element;
31 
32 import org.openoffice.xmerge.Document;
33 import org.openoffice.xmerge.ConverterCapabilities;
34 import org.openoffice.xmerge.converter.xml.OfficeDocument;
35 import org.openoffice.xmerge.converter.xml.sxw.SxwDocument;
36 import org.openoffice.xmerge.converter.xml.*;
37 
38 /**
39  *  <p>This class represents a font table in a WordSmith document.
40  *  A font table is represented as follows:</p>
41  *
42  *  <p><blockquote>
43  *   binary "3"<br>
44  *   two-byte length of the table of strings which follows<br>
45  *   string table (null-terminated strings) representing font names
46  *  </blockquote></p>
47  *
48  *  @author   David Proulx
49  */
50 class WseFontTable extends Wse {
51 
52     java.util.Vector fontNames = new java.util.Vector(10);
53 
54 
55     /**
56      *  Constructor for use when going from DOM to WordSmith.
57      */
WseFontTable()58     public WseFontTable() {
59     }
60 
61 
62     /**
63      *  Constructor for use when going from WordSmith to DOM.
64      *
65      *  @param  dataArray  <code>byte</code> array.
66      *  @param  i          The index.
67      */
WseFontTable(byte dataArray[], int i)68     public WseFontTable(byte dataArray[], int i) {
69         i++;
70         int tableLen = ((dataArray[i] << 8) | (dataArray[i+1] & 0xFF));
71         i += 2;
72         while (tableLen > 0) {
73             int j = 0;
74             while (dataArray[i + j] != 0) j++;
75             fontNames.add(new String(dataArray, i, j));
76             tableLen -= (j + 1);
77             i += (j + 1);
78         }
79     }
80 
81 
82     /**
83      *  Add a new font to the table.
84      *
85      *  @param  newFontName  The new font name.
86      */
add(String newFontName)87     public void add(String newFontName) {
88         if (newFontName != null)
89             fontNames.add(newFontName);
90     }
91 
92 
93     /**
94      *  Return a font name from the table, or null if invalid index.
95      *
96      *  @param  index  The font name index.
97      *
98      *  @return  The font name.
99      */
getFontName(int index)100     public String getFontName(int index) {
101         try {
102             return (String)fontNames.elementAt(index);
103         } catch (ArrayIndexOutOfBoundsException e) {
104             return null;
105         }
106     }
107 
108     /**
109      *  Return the index of a font name in the table, or -1 if not found.
110      *
111      *  @param fontName  The font name.
112      *
113      *  @return  The index of the font name, or -1 if not found.
114      */
getFontIndex(String fontName)115     public int getFontIndex(String fontName) {
116         int len = fontNames.size();
117         for (int i = 0; i < len; i++) {
118             String name = (String) fontNames.elementAt(i);
119             if (name.equals(fontName))
120                 return i;
121         }
122         return -1;
123     }
124 
125 
126     /**
127      *  Compute the index of the first <code>byte</code> following the
128      *  paragraph descriptor, assuming that
129      *  <code>dataArray[startIndex]</code> is the beginning of a valid
130      *  paragraph descriptor.
131      *
132      *  @param dataArray   <code>byte</code> array.
133      *  @param startIndex  The start index.
134      *
135      *  @return  The index of the first <code>byte</code> following the
136      *           paragraph description.
137      */
computeNewIndex(byte dataArray[], int startIndex)138     static int computeNewIndex(byte dataArray[], int startIndex) {
139         startIndex++;  // Skip the leading "3"
140         int tableLen = ((dataArray[startIndex] << 8) | (dataArray[startIndex+1] & 0xFF));
141         tableLen &= 0xFFFF;  // eliminate problems with sign-extension
142         return startIndex + tableLen + 2;
143     }
144 
145 
146     /**
147      *  Return true if <code>dataArray[startIndex]</code> is the start of a
148      *  valid paragraph descriptor.
149      *
150      *  @param  dataArray   <code>byte</code> string.
151      *  @param  startIndex  Start index.
152      *
153      *  @return  true if <code>dataArray[startIndex]</code> is the start
154      *           of a valid paragraph descriptor, false otherwise.
155      */
isValid(byte dataArray[], int startIndex)156     static boolean isValid(byte dataArray[], int startIndex) {
157         try {
158             if (dataArray[startIndex] != 3)
159                 return false;
160             int len = ((dataArray[startIndex+1] << 8)
161               | (dataArray[startIndex+2] & 0xFF));
162             len &= 0xFFFF;  // eliminate problems with sign-extension
163 
164             if (dataArray[startIndex + len + 2] != 0)
165                 return false;
166         } catch (ArrayIndexOutOfBoundsException e) {
167             return false;
168         }
169         return true;
170     }
171 
172 
173     /**
174      *  Return the number of bytes needed to represent this font table.
175      *
176      *  @return The number of bytes needed to represent this font table.
177      */
getByteCount()178     int getByteCount() {
179 
180         int length = 3;  // leading "3" plus 2 bytes for length.
181         int nFonts = fontNames.size();
182         for (int i = 0; i < nFonts; i++) {
183             String name = (String)fontNames.elementAt(i);
184             length += name.length() + 1;  // extra byte is for trailing "0"
185         }
186         return length;
187     }
188 
189     /**
190      *  Return a <code>byte</code> array representing this font table.
191      *
192      *  @return  An <code>byte</code> array representing this font table.
193      */
getBytes()194     byte[] getBytes() {
195 
196         int length = getByteCount();
197         int nFonts = fontNames.size();
198         byte b[] = new byte[length];
199         b[0] = 3;
200         length -= 3;
201         b[1] = (byte)(length >> 8);
202         b[2] = (byte)(length & 0xFF);
203         int indx = 3;
204         for (int i = 0; i < nFonts; i++) {
205             String name = (String)fontNames.elementAt(i);
206             byte bname[] = name.getBytes();
207             System.arraycopy(bname, 0, b, indx, bname.length);
208             indx += bname.length;
209             b[indx++] = 0;
210         }
211         return b;
212     }
213 }
214 
215