1
2 package org.freehep.graphicsio.swf;
3
4 import java.awt.Color;
5 import java.awt.geom.AffineTransform;
6 import java.awt.geom.Rectangle2D;
7 import java.io.IOException;
8 import java.util.Vector;
9
10 import org.freehep.util.io.BitOutputStream;
11
12
13
14
15
16
17
18
19 public class DefineText extends DefinitionTag {
20
21 protected int character;
22
23 protected Rectangle2D bounds;
24
25 protected AffineTransform matrix;
26
27 protected Vector
28
29 public DefineText(int id, Rectangle2D bounds, AffineTransform matrix,
30 Vector
31 this();
32 character = id;
33 this.bounds = bounds;
34 this.matrix = matrix;
35 this.text = text;
36 }
37
38 public DefineText() {
39 super(11, 1);
40 }
41
42 protected DefineText(int tagID, int version) {
43 super(tagID, version);
44 }
45
46 public SWFTag read(int tagID, SWFInputStream swf, int len)
47 throws IOException {
48 DefineText tag = new DefineText();
49 tag.read(tagID, swf, len, false);
50 return tag;
51 }
52
53 protected void read(int tagID, SWFInputStream swf, int len, boolean hasAlpha)
54 throws IOException {
55
56 character = swf.readUnsignedShort();
57 swf.getDictionary().put(character, this);
58
59 bounds = swf.readRect();
60 matrix = swf.readMatrix();
61 int glyphBits = swf.readUnsignedByte();
62 int advanceBits = swf.readUnsignedByte();
63
64 text = new Vector();
65 boolean type1 = swf.readBitFlag();
66 Record record = type1 ? (Record) new RecordType1(swf, glyphBits,
67 advanceBits, hasAlpha) : (Record) new RecordType0(swf,
68 glyphBits, advanceBits);
69 while (!record.isEndRecord()) {
70 text.add(record);
71 type1 = swf.readBitFlag();
72 record = type1 ? (Record) new RecordType1(swf, glyphBits,
73 advanceBits, hasAlpha) : (Record) new RecordType0(swf,
74 glyphBits, advanceBits);
75 }
76 }
77
78 public void write(int tagID, SWFOutputStream swf) throws IOException {
79
80 write(swf, false);
81 }
82
83 protected void write(SWFOutputStream swf, boolean hasAlpha)
84 throws IOException {
85
86 swf.writeUnsignedShort(character);
87 swf.writeRect(bounds);
88 swf.writeMatrix(matrix);
89 int glyphBits = 0;
90 int advanceBits = 0;
91 for (int i = 0; i < text.size(); i++) {
92 Record t = (Record) text.get(i);
93 if (t instanceof RecordType0) {
94 RecordType0 t0 = (RecordType0) t;
95 glyphBits = Math.max(glyphBits, t0.getGlyphBits());
96 advanceBits = Math.max(advanceBits, t0.getAdvanceBits());
97 }
98 }
99
100 swf.writeUnsignedByte(glyphBits);
101 swf.writeUnsignedByte(advanceBits);
102
103 for (int i = 0; i < text.size(); i++) {
104 Record t = (Record) text.get(i);
105 t.write(swf, glyphBits, advanceBits, hasAlpha);
106 }
107 swf.writeUnsignedByte(0);
108 }
109
110 public String toString() {
111 StringBuffer s = new StringBuffer();
112 s.append(super.toString() + "\n");
113 s.append(" character: " + character + "\n");
114 s.append(" bounds: " + bounds + "\n");
115 s.append(" matrix: " + matrix + "\n");
116 s.append(" texts: " + text.size() + "\n");
117 for (int i = 0; i < text.size(); i++) {
118 s.append(text.get(i) + "\n");
119 }
120 return s.toString();
121 }
122
123
124
125
126 public static abstract class Record {
127 public abstract void write(SWFOutputStream swf, int glyphBits,
128 int advanceBits, boolean hasAlpha) throws IOException;
129
130 public abstract boolean isEndRecord();
131 }
132
133
134
135
136 public static class RecordType0 extends Record {
137 private Vector
138
139 public RecordType0() {
140 this.glyphs = new Vector();
141 }
142
143 public void add(GlyphEntry glyph) {
144 glyphs.add(glyph);
145 }
146
147 RecordType0(SWFInputStream swf, int glyphBits, int advanceBits)
148 throws IOException {
149
150 int glyphCount = (int) swf.readUBits(7);
151 if (glyphCount == 0)
152 return;
153
154 glyphs = new Vector();
155 for (int i = 0; i < glyphCount; i++) {
156 GlyphEntry entry = new GlyphEntry(swf, glyphBits, advanceBits);
157 glyphs.add(entry);
158 }
159 swf.byteAlign();
160 }
161
162 public void write(SWFOutputStream swf, int glyphBits, int advanceBits,
163 boolean hasAlpha) throws IOException {
164
165 swf.writeUBits(0, 1);
166 swf.writeUBits(glyphs.size(), 7);
167 for (int i = 0; i < glyphs.size(); i++) {
168 ((GlyphEntry) glyphs.get(i)).write(swf, glyphBits, advanceBits);
169 }
170 swf.byteAlign();
171 }
172
173 public boolean isEndRecord() {
174 return glyphs == null;
175 }
176
177 public int getGlyphBits() {
178 int glyphBits = 0;
179 for (int i = 0; i < glyphs.size(); i++) {
180 glyphBits = Math.max(glyphBits, ((GlyphEntry) glyphs.get(i))
181 .getGlyphBits());
182 }
183 return glyphBits;
184 }
185
186 public int getAdvanceBits() {
187 int advanceBits = 0;
188 for (int i = 0; i < glyphs.size(); i++) {
189 advanceBits = Math.max(advanceBits,
190 ((GlyphEntry) glyphs.get(i)).getAdvanceBits());
191 }
192 return advanceBits;
193 }
194
195 public String toString() {
196 StringBuffer s = new StringBuffer();
197 s.append(" glyphCount: " + glyphs.size() + "\n");
198 s.append(" ");
199 for (int i = 0; i < glyphs.size(); i++) {
200 s.append(glyphs.get(i) + " ");
201 }
202 s.append("\n");
203 return s.toString();
204 }
205 }
206
207
208
209
210 public static class RecordType1 extends Record {
211 private int fontID = -1;
212
213 private Color color;
214
215 private int xOffset, yOffset;
216
217 private int height;
218
219
220 private Vector
221
222 public RecordType1(int fontID, Color color, int xOffset, int yOffset,
223 int height) {
224 this.fontID = fontID;
225 this.color = color;
226 this.xOffset = xOffset;
227 this.yOffset = yOffset;
228 this.height = height;
229
230 glyphs = new Vector();
231 }
232
233
234 public void add(GlyphEntry glyph) {
235 glyphs.add(glyph);
236 }
237
238 RecordType1(SWFInputStream input, int glyphBits, int advanceBits,
239 boolean hasAlpha) throws IOException {
240
241 boolean hasFont = input.readBitFlag();
242 boolean hasColor = input.readBitFlag();
243 boolean hasYOffset = input.readBitFlag();
244 boolean hasXOffset = input.readBitFlag();
245
246 if (hasFont)
247 fontID = input.readUnsignedShort();
248 if (hasColor)
249 color = input.readColor(hasAlpha);
250 if (hasXOffset)
251 xOffset = input.readShort();
252 if (hasYOffset)
253 yOffset = input.readShort();
254 if (hasFont)
255 height = input.readUnsignedShort();
256
257 glyphs = new Vector();
258 if (input.getVersion() >= 7) {
259 int glyphCount = (int) input.readUnsignedByte();
260 for (int i = 0; i < glyphCount; i++) {
261 glyphs.add(new GlyphEntry(input, glyphBits, advanceBits));
262 }
263 }
264 }
265
266 public void write(SWFOutputStream swf, int glyphBits, int advanceBits,
267 boolean hasAlpha) throws IOException {
268
269 swf.writeBitFlag(true);
270 swf.writeUBits(0, 3);
271 swf.writeBitFlag(fontID >= 0);
272 swf.writeBitFlag(color != null);
273 swf.writeBitFlag(yOffset != 0);
274 swf.writeBitFlag(xOffset != 0);
275
276 if (fontID >= 0)
277 swf.writeUnsignedShort(fontID);
278 if (color != null)
279 swf.writeColor(color, hasAlpha);
280 if (xOffset != 0)
281 swf.writeShort(xOffset);
282 if (yOffset != 0)
283 swf.writeShort(yOffset);
284 if (fontID >= 0)
285 swf.writeUnsignedShort(height);
286
287 if (swf.getVersion() >= 7) {
288 swf.writeUnsignedByte(glyphs.size());
289 for (int i = 0; i < glyphs.size(); i++) {
290 ((GlyphEntry) glyphs.get(i)).write(swf, glyphBits,
291 advanceBits);
292 }
293 }
294 }
295
296 public int getGlyphBits() {
297 int glyphBits = 0;
298 for (int i = 0; i < glyphs.size(); i++) {
299 glyphBits = Math.max(glyphBits, ((GlyphEntry) glyphs.get(i))
300 .getGlyphBits());
301 }
302 return glyphBits;
303 }
304
305 public int getAdvanceBits() {
306 int advanceBits = 0;
307 for (int i = 0; i < glyphs.size(); i++) {
308 advanceBits = Math.max(advanceBits,
309 ((GlyphEntry) glyphs.get(i)).getAdvanceBits());
310 }
311 return advanceBits;
312 }
313
314 public boolean isEndRecord() {
315 return false;
316 }
317
318 public String toString() {
319 StringBuffer s = new StringBuffer();
320 s.append(" FontID: " + fontID + "\n");
321 s.append(" Color: " + color + "\n");
322 s.append(" xOffset: " + xOffset + "\n");
323 s.append(" yOffset: " + yOffset + "\n");
324 s.append(" height: " + height + "\n");
325 s.append(" glyphCount (swf >= 7): " + glyphs.size() + "\n");
326 s.append(" ");
327 for (int i = 0; i < glyphs.size(); i++) {
328 s.append(glyphs.get(i) + " ");
329 }
330 s.append("\n");
331 return s.toString();
332 }
333 }
334
335 public static class GlyphEntry {
336
337 private int index;
338
339 private int advance;
340
341 public GlyphEntry(int index, int advance) {
342 this.index = index;
343 this.advance = advance;
344 }
345
346 public GlyphEntry(SWFInputStream input, int glyphBits, int advanceBits)
347 throws IOException {
348 index = (int) input.readUBits(glyphBits);
349 advance = (int) input.readSBits(advanceBits);
350 }
351
352 public void write(SWFOutputStream swf, int glyphBits, int advanceBits)
353 throws IOException {
354
355 swf.writeUBits(index, glyphBits);
356 swf.writeSBits(advance, advanceBits);
357 }
358
359 public int getGlyphBits() {
360 return BitOutputStream.minBits(index, false);
361 }
362
363 public int getAdvanceBits() {
364 return BitOutputStream.minBits(advance, true);
365 }
366
367 public String toString() {
368 return "GlyphEntry[" + index + "," + advance + "]";
369 }
370 }
371 }