001: /*
002: * $Id: TextRecord.java,v 1.3 2002/04/15 00:49:45 skavish Exp $
003: *
004: * ==========================================================================
005: *
006: * The JGenerator Software License, Version 1.0
007: *
008: * Copyright (c) 2000 Dmitry Skavish (skavish@usa.net). All rights reserved.
009: *
010: * Redistribution and use in source and binary forms, with or without
011: * modification, are permitted provided that the following conditions are met:
012: *
013: * 1. Redistributions of source code must retain the above copyright
014: * notice, this list of conditions and the following disclaimer.
015: *
016: * 2. Redistributions in binary form must reproduce the above copyright
017: * notice, this list of conditions and the following disclaimer in
018: * the documentation and/or other materials provided with the
019: * distribution.
020: *
021: * 3. The end-user documentation included with the redistribution, if
022: * any, must include the following acknowlegement:
023: * "This product includes software developed by Dmitry Skavish
024: * (skavish@usa.net, http://www.flashgap.com/)."
025: * Alternately, this acknowlegement may appear in the software itself,
026: * if and wherever such third-party acknowlegements normally appear.
027: *
028: * 4. The name "The JGenerator" must not be used to endorse or promote
029: * products derived from this software without prior written permission.
030: * For written permission, please contact skavish@usa.net.
031: *
032: * 5. Products derived from this software may not be called "The JGenerator"
033: * nor may "The JGenerator" appear in their names without prior written
034: * permission of Dmitry Skavish.
035: *
036: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
037: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
038: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
039: * DISCLAIMED. IN NO EVENT SHALL DMITRY SKAVISH OR THE OTHER
040: * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
041: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
042: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
043: * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
044: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
045: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
046: * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
047: * SUCH DAMAGE.
048: *
049: */
050:
051: package org.openlaszlo.iv.flash.api.text;
052:
053: import org.openlaszlo.iv.flash.parser.*;
054: import org.openlaszlo.iv.flash.util.*;
055: import org.openlaszlo.iv.flash.api.*;
056: import java.io.*;
057: import java.util.*;
058:
059: /**
060: * TextRecord.
061: * <p>
062: * Defines a text of one style.
063: *
064: * @author Dmitry Skavish
065: * @see TextStyleChangeRecord
066: */
067: public final class TextRecord extends FlashItem {
068:
069: private int size; // size of the text (number of characters)
070: private char[] text; // the text itself ('size' characters)
071: private int[] indexes; // indexes of the text in font's codetable
072: private int[] advances; // advance values of the text in TWIXELS!
073:
074: public TextRecord() {
075: }
076:
077: /**
078: * Creates text record of zero size and of specified capacity
079: *
080: * @param maxSize capacity of created text record
081: */
082: public TextRecord(int maxSize) {
083: text = new char[maxSize];
084: indexes = new int[maxSize];
085: advances = new int[maxSize];
086: size = 0;
087: }
088:
089: // public void setText( char[] text ) { this.text = text; }
090: // public void setIndexes( int[] indexes ) { this.indexes = indexes; }
091: // public void setAdvances( int[] advances ) { this.advances = advances; }
092:
093: public char[] getText() {
094: return text;
095: }
096:
097: public int[] getIndexes() {
098: return indexes;
099: }
100:
101: public int[] getAdvances() {
102: return advances;
103: }
104:
105: /**
106: * Returns character at specified index
107: *
108: * @param i index of the character to be returned
109: * @return character at specified index
110: */
111: public char getChar(int i) {
112: return text[i];
113: }
114:
115: /**
116: * Returns character's index at specified index
117: *
118: * @param i index of the character's index to be returned
119: * @return character's index at specified index
120: */
121: public int getIndex(int i) {
122: return indexes[i];
123: }
124:
125: /**
126: * Returns advance value at specified index
127: *
128: * @param i index of the advance value to be returned
129: * @return advance value at specified index
130: */
131: public int getAdvance(int i) {
132: return advances[i];
133: }
134:
135: /**
136: * Sets new character at specified index
137: *
138: * @param i index of the character to be set
139: * @param ch character to be set
140: */
141: public void setChar(int i, char ch) {
142: text[i] = ch;
143: }
144:
145: /**
146: * Sets new character's index at specified index
147: *
148: * @param i index of the character's index to be set
149: * @param index character's index to be set
150: */
151: public void setIndex(int i, int index) {
152: indexes[i] = index;
153: }
154:
155: /**
156: * Sets new advance value at specified index
157: *
158: * @param i index of the advance value to be set
159: * @param ch advance value to be set
160: */
161: public void setAdvance(int i, int advance) {
162: advances[i] = advance;
163: }
164:
165: /**
166: * Returns size of the text
167: *
168: * @return size of the text
169: */
170: public int getSize() {
171: return size;
172: }
173:
174: /**
175: * Sets new size of the text
176: *
177: * @param size new size of the text
178: */
179: public void setSize(int size) {
180: this .size = size;
181: }
182:
183: /**
184: * Returns width of the text in twixels
185: *
186: * @return width of the text in twixels
187: */
188: public int getWidth() {
189: int width = 0;
190: for (int i = 0; i < size; i++) {
191: width += advances[i];
192: }
193: return width;
194: }
195:
196: /**
197: * Updates indexes of this record from specified font
198: *
199: * @param font font to update from
200: */
201: public void updateIndexes(Font font) {
202: for (int i = 0; i < size; i++) {
203: char ch = text[i];
204: //System.out.print( "text["+i+"]='"+ch+"'" );
205: int idx = font.getIndex(ch);
206: //System.out.println( ", new index="+idx );
207: if (idx == -1)
208: idx = 0; // just for safety
209: indexes[i] = idx;
210: }
211: }
212:
213: /**
214: * Adds new index and advance value.
215: * <P>
216: * Does not check for overflow.
217: *
218: * @param index new index to be added
219: * @param advance new advance value to be added
220: */
221: public void add(int index, int advance) {
222: indexes[size] = index;
223: advances[size] = advance;
224: size++;
225: }
226:
227: /**
228: * Adds new character, index and advance value.
229: * <P>
230: * Does not check for overflow.
231: *
232: * @param ch new character to be added
233: * @param index new index to be added
234: * @param advance new advance value to be added
235: */
236: public void add(char ch, int index, int advance) {
237: text[size] = ch;
238: add(index, advance);
239: }
240:
241: /**
242: * Trims this record from the end
243: * <P>
244: * Removes all spaces from the end
245: *
246: * @return width in twixels of all removed spaces
247: */
248: public int trimEnd() {
249: int i;
250: int w = 0;
251: for (i = size; --i >= 0;) {
252: if (!Character.isWhitespace(text[i]))
253: break;
254: w += advances[i];
255: }
256: size = i + 1;
257: return w;
258: }
259:
260: /**
261: * Trims this record from the start
262: * <P>
263: * Removes all spaces from the start
264: *
265: * @return width in twixels of all removed spaces
266: */
267: public int trimStart() {
268: int i;
269: int w = 0;
270: for (i = 0; i < size; i++) {
271: if (!Character.isWhitespace(text[i]))
272: break;
273: w += advances[i];
274: }
275: if (i != 0) {
276: size -= i;
277: System.arraycopy(text, i, text, 0, size);
278: System.arraycopy(advances, i, advances, 0, size);
279: System.arraycopy(indexes, i, indexes, 0, size);
280: }
281: return w;
282: }
283:
284: /**
285: * Returns maximum index
286: *
287: * @return maximum index
288: */
289: public int getMaxIndex() {
290: return Util.getMax(indexes, size);
291: }
292:
293: /**
294: * Returns maximum advance value
295: *
296: * @return maximum advance value
297: */
298: public int getMaxAdvance() {
299: return Util.getMax(advances, size);
300: }
301:
302: /**
303: * Writes this text record to flash buffer.
304: * <P>
305: * Expects two-element integer array in userdata of flashbuffer.
306: * First element is number of glyph bits and second - number of
307: * advance value bits.
308: *
309: * @param fob flashbuffer to write to
310: */
311: public void write(FlashOutput fob) {
312: int[] nbits = (int[]) fob.getUserData();
313: int nGlyphBits = nbits[0];
314: int nAdvanceBits = nbits[1];
315: fob.writeByte(size);
316: for (int k = 0; k < size; k++) {
317: fob.writeBits(indexes[k], nGlyphBits);
318: fob.writeBits(advances[k], nAdvanceBits);
319: }
320: fob.flushBits();
321: }
322:
323: public void printContent(PrintStream out, String indent) {
324: out.println(indent + "TextRecord: nGlyphs=" + size);
325: for (int k = 0; k < size; k++) {
326: out.println(indent + " char[" + k + "]='" + text[k]
327: + "', advance[" + k + "]=" + advances[k]);
328: }
329: }
330:
331: protected FlashItem copyInto(FlashItem item, ScriptCopier copier) {
332: char[] txt = new char[text.length];
333: System.arraycopy(text, 0, txt, 0, text.length);
334: int[] ind = new int[indexes.length];
335: System.arraycopy(indexes, 0, ind, 0, indexes.length);
336: int[] adv = new int[advances.length];
337: System.arraycopy(advances, 0, adv, 0, advances.length);
338: ((TextRecord) item).size = size;
339: ((TextRecord) item).text = txt;
340: ((TextRecord) item).indexes = ind;
341: ((TextRecord) item).advances = adv;
342: return item;
343: }
344:
345: public FlashItem getCopy(ScriptCopier copier) {
346: return copyInto(new TextRecord(), copier);
347: }
348: }
|