1
2 package org.freehep.graphicsio.swf;
3
4 import java.awt.geom.Rectangle2D;
5 import java.io.IOException;
6
7
8
9
10
11
12
13
14
15 public class DefineFont2 extends DefinitionTag implements SWFConstants {
16
17 private int character;
18
19 private boolean shiftJIS = false;
20
21 private boolean ansi = false;
22
23 private boolean wideOffsets = false;
24
25 private boolean wideCodes = false;
26
27 private boolean italic = false;
28
29 private boolean bold = false;
30
31 private int languageCode;
32
33 private String name;
34
35 private long[] offsets;
36
37 private long codeOffset;
38
39 private SWFShape[] shapes;
40
41 private int[] codes;
42
43 private int ascent, descent, leading;
44
45 private short[] advances;
46
47 private Rectangle2D[] bounds;
48
49 private KerningRecord[] kerning = new KerningRecord[0];
50
51 public DefineFont2() {
52 super(48, 3);
53 }
54
55 public DefineFont2(int character, boolean italic, boolean bold,
56 String name, SWFShape[] shapes, int[] codes) {
57 this(character, false, false, italic, bold, true, true, LANGUAGE_LATIN,
58 name, shapes, codes, 0, 0, 0, null, null, null);
59 }
60
61 public DefineFont2(int character, boolean shiftJIS, boolean ansi,
62 boolean italic, boolean bold, boolean wideOffsets,
63 boolean wideCodes, int languageCode, String name,
64 SWFShape[] shapes, int[] codes, int ascent, int descent,
65 int leading, short[] advances, Rectangle2D[] bounds,
66 KerningRecord[] kerning) {
67 this();
68 this.character = character;
69 this.shiftJIS = shiftJIS;
70 this.ansi = ansi;
71 this.italic = italic;
72 this.bold = bold;
73 this.wideOffsets = wideOffsets;
74 this.wideCodes = wideCodes;
75 this.languageCode = languageCode;
76 this.name = name;
77 this.shapes = shapes;
78 this.codes = codes;
79 this.ascent = ascent;
80 this.descent = descent;
81 this.leading = leading;
82 this.advances = advances;
83 this.bounds = bounds;
84 this.kerning = kerning;
85 }
86
87 public SWFTag read(int tagID, SWFInputStream swf, int len)
88 throws IOException {
89
90 DefineFont2 tag = new DefineFont2();
91 tag.character = swf.readUnsignedShort();
92 swf.getDictionary().put(tag.character, tag);
93
94 boolean hasLayout = swf.readBitFlag();
95 tag.shiftJIS = swf.readBitFlag();
96
97 tag.ansi = swf.readBitFlag();
98 tag.wideOffsets = swf.readBitFlag();
99 tag.wideCodes = swf.readBitFlag();
100 tag.italic = swf.readBitFlag();
101 tag.bold = swf.readBitFlag();
102 tag.languageCode = swf.readLanguageCode();
103
104 int nameLength = swf.readUnsignedByte();
105 if (swf.getVersion() >= 6) {
106 tag.name = swf.readUTF();
107 } else {
108 tag.name = new String(swf.readByte(nameLength));
109 }
110
111 int glyphCount = swf.readUnsignedShort();
112
113 tag.offsets = new long[glyphCount];
114 for (int i = 0; i < glyphCount; i++) {
115 tag.offsets[i] = (tag.wideOffsets) ? swf.readUnsignedInt()
116 : (long) swf.readUnsignedShort();
117 }
118
119 tag.codeOffset = (tag.wideOffsets) ? swf.readUnsignedInt() : (long) swf
120 .readUnsignedShort();
121
122 tag.shapes = new SWFShape[glyphCount];
123 for (int i = 0; i < glyphCount; i++) {
124 tag.shapes[i] = new SWFShape(swf);
125 }
126
127 tag.codes = (tag.wideCodes) ? swf.readUnsignedShort(glyphCount) : swf
128 .readUnsignedByte(glyphCount);
129
130 if (hasLayout) {
131 tag.ascent = swf.readShort();
132 tag.descent = swf.readShort();
133 tag.leading = swf.readShort();
134 tag.advances = swf.readShort(glyphCount);
135 tag.bounds = new Rectangle2D[glyphCount];
136 for (int i = 0; i < glyphCount; i++) {
137 tag.bounds[i] = swf.readRect();
138 }
139
140 int kerningCount = swf.readUnsignedShort();
141 tag.kerning = new KerningRecord[kerningCount];
142 for (int i = 0; i < kerningCount; i++) {
143 tag.kerning[i] = new KerningRecord(swf, tag.wideCodes);
144 }
145 }
146 return tag;
147 }
148
149 public void write(int tagID, SWFOutputStream swf) throws IOException {
150 boolean hasLayout = (ascent != 0) || (descent != 0) || (leading != 0)
151 || (advances != null) || (bounds != null) || (kerning != null);
152
153 swf.writeUnsignedShort(character);
154 swf.writeBitFlag(hasLayout);
155 swf.writeBitFlag(shiftJIS);
156 swf.writeUBits(0, 1);
157 swf.writeBitFlag(ansi);
158 swf.writeBitFlag(wideOffsets);
159 swf.writeBitFlag(wideCodes);
160 swf.writeBitFlag(italic);
161 swf.writeBitFlag(bold);
162 if (swf.getVersion() >= 6) {
163 swf.writeLanguageCode(languageCode);
164 } else {
165 swf.writeUnsignedByte(0);
166 }
167
168 swf.writeUnsignedByte(name.length());
169 if (swf.getVersion() >= 6) {
170 swf.writeUTF(name);
171 } else {
172 swf.writeByte(name.getBytes());
173 }
174
175
176 swf.pushBuffer();
177 int[] offsets = new int[shapes.length];
178 int inc = wideOffsets ? 4 : 2;
179 inc = (offsets.length + 1) * inc;
180 for (int i = 0; i < shapes.length; i++) {
181 offsets[i] = swf.getBufferLength() + inc;
182 shapes[i].write(swf);
183 swf.byteAlign();
184 }
185 codeOffset = swf.getBufferLength() + inc;
186 swf.popBuffer();
187 swf.writeUnsignedShort(offsets.length);
188
189
190 for (int i = 0; i < offsets.length; i++) {
191 if (wideOffsets) {
192 swf.writeUnsignedInt(offsets[i]);
193 } else {
194 swf.writeUnsignedShort((int) offsets[i]);
195 }
196 }
197 if (wideOffsets) {
198 swf.writeUnsignedInt(codeOffset);
199 } else {
200 swf.writeUnsignedShort((int) codeOffset);
201 }
202 swf.append();
203
204 if (wideCodes) {
205 for (int i = 0; i < offsets.length; i++) {
206 swf.writeUnsignedShort(codes[i]);
207 }
208 } else {
209 for (int i = 0; i < offsets.length; i++) {
210 swf.writeUnsignedByte(codes[i]);
211 }
212 }
213 if (hasLayout) {
214 swf.writeShort(ascent);
215 swf.writeShort(descent);
216 swf.writeShort(leading);
217 for (int i = 0; i < offsets.length; i++) {
218 swf.writeShort(advances[i]);
219 }
220 for (int i = 0; i < bounds.length; i++) {
221 swf.writeRect(bounds[i]);
222 }
223 swf.writeUnsignedShort(kerning.length);
224 for (int i = 0; i < kerning.length; i++) {
225 kerning[i].write(swf, wideCodes);
226 }
227 }
228 }
229
230 public long getId() {
231 return character;
232 }
233
234 public boolean getShiftJIS() {
235 return shiftJIS;
236 }
237
238 public boolean isAnsi() {
239 return ansi;
240 }
241
242 public boolean isItalic() {
243 return italic;
244 }
245
246 public boolean isBold() {
247 return bold;
248 }
249
250 public boolean hasWideOffsets() {
251 return wideOffsets;
252 }
253
254 public boolean hasWideCodes() {
255 return wideCodes;
256 }
257
258 public String getName() {
259 return name;
260 }
261
262 public SWFShape[] getShapes() {
263 return shapes;
264 }
265
266 public int[] getCodes() {
267 return codes;
268 }
269
270 public int getAscent() {
271 return ascent;
272 }
273
274 public int getDescent() {
275 return descent;
276 }
277
278 public int getLeading() {
279 return leading;
280 }
281
282 public short[] getAdvances() {
283 return advances;
284 }
285
286 public Rectangle2D[] getBounds() {
287 return bounds;
288 }
289
290 public KerningRecord[] getKerning() {
291 return kerning;
292 }
293
294 public void setId(int id) {
295 this.character = id;
296 }
297
298 public void setShiftJIS(boolean shiftJIS) {
299 this.shiftJIS = shiftJIS;
300 }
301
302 public void setAnsi(boolean ansi) {
303 this.ansi = ansi;
304 }
305
306 public void setItalic(boolean italic) {
307 this.italic = italic;
308 }
309
310 public void setBold(boolean bold) {
311 this.bold = bold;
312 }
313
314 public void setWideOffsets(boolean wideOffsets) {
315 this.wideOffsets = wideOffsets;
316 }
317
318 public void setWideCodes(boolean wideCodes) {
319 this.wideCodes = wideCodes;
320 }
321
322 public void setName(String name) {
323 this.name = name;
324 }
325
326 public void setCodes(int[] codes) {
327 this.codes = codes;
328 }
329
330 public void setShapes(SWFShape[] shapes) {
331 this.shapes = shapes;
332 }
333
334 public void setAscent(int ascent) {
335 this.ascent = ascent;
336 }
337
338 public void setDescent(int descent) {
339 this.descent = descent;
340 }
341
342 public void setLeading(int leading) {
343 this.leading = leading;
344 }
345
346 public void setAdvances(short[] advances) {
347 this.advances = advances;
348 }
349
350 public void setAdvances(int[] advances) {
351 short[] s = new short[advances.length];
352 for (int i = 0; i < s.length; i++) {
353 s[i] = (short) advances[i];
354 }
355 setAdvances(s);
356 }
357
358 public void setBounds(Rectangle2D[] bounds) {
359 this.bounds = bounds;
360 }
361
362 public void setKerning(KerningRecord[] kerning) {
363 this.kerning = kerning;
364 }
365
366 public String toString() {
367
368 StringBuffer s = new StringBuffer();
369 s.append(super.toString() + "\n");
370 s.append(" character: " + character + "\n");
371 s.append(" name: " + name + "\n");
372 if (shiftJIS)
373 s.append(" shiftJIS\n");
374 if (ansi)
375 s.append(" ansi\n");
376 if (italic)
377 s.append(" italic\n");
378 if (bold)
379 s.append(" bold\n");
380 if (wideOffsets)
381 s.append(" wideOffsets\n");
382 if (wideCodes)
383 s.append(" wideCodes\n");
384 if (languageCode > 0)
385 s.append(" languageCode: " + languageCode + "\n");
386 if (ascent != 0)
387 s.append(" ascent: " + ascent + "\n");
388 if (descent != 0)
389 s.append(" descent: " + descent + "\n");
390 if (leading != 0)
391 s.append(" leading: " + leading + "\n");
392 if (advances != null) {
393 for (int i = 0; i < advances.length; i++) {
394 s.append(" advances[" + i + "]: " + advances[i] + "\n");
395 }
396 }
397 if (bounds != null) {
398 for (int i = 0; i < bounds.length; i++) {
399 s.append(" bounds[" + i + "]: " + bounds[i] + "\n");
400 }
401 }
402 s.append(" glyphCount: " + shapes.length + "\n");
403 for (int i = 0; i < shapes.length; i++) {
404 s.append(" >>> Shape " + i + "\n");
405 s.append(shapes[i] + "\n");
406 }
407
408 return s.toString();
409 }
410
411 public static class KerningRecord {
412
413 private int code1, code2;
414
415 private int adjustment;
416
417 public KerningRecord(int code1, int code2, int adjustment) {
418 this.code1 = code1;
419 this.code2 = code2;
420 this.adjustment = adjustment;
421 }
422
423 public KerningRecord(SWFInputStream input, boolean wideCodes)
424 throws IOException {
425
426 code1 = (wideCodes) ? input.readUnsignedShort() : input
427 .readUnsignedByte();
428 code2 = (wideCodes) ? input.readUnsignedShort() : input
429 .readUnsignedByte();
430 adjustment = input.readShort();
431 }
432
433 public void write(SWFOutputStream swf, boolean wideCodes)
434 throws IOException {
435
436 if (wideCodes)
437 swf.writeUnsignedShort(code1);
438 else
439 swf.writeUnsignedByte(code1);
440 if (wideCodes)
441 swf.writeUnsignedShort(code2);
442 else
443 swf.writeUnsignedByte(code2);
444 swf.writeShort(adjustment);
445 }
446
447 public String toString() {
448 return "Kerning[" + code1 + ", " + code2 + ", " + adjustment + "]";
449 }
450 }
451
452 }