KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > openlaszlo > iv > flash > api > text > FontDef


1 /*
2  * $Id: FontDef.java,v 1.3 2002/02/24 02:10:19 skavish Exp $
3  *
4  * ==========================================================================
5  *
6  * The JGenerator Software License, Version 1.0
7  *
8  * Copyright (c) 2000 Dmitry Skavish (skavish@usa.net). All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions are met:
12  *
13  * 1. Redistributions of source code must retain the above copyright
14  * notice, this list of conditions and the following disclaimer.
15  *
16  * 2. Redistributions in binary form must reproduce the above copyright
17  * notice, this list of conditions and the following disclaimer in
18  * the documentation and/or other materials provided with the
19  * distribution.
20  *
21  * 3. The end-user documentation included with the redistribution, if
22  * any, must include the following acknowlegement:
23  * "This product includes software developed by Dmitry Skavish
24  * (skavish@usa.net, http://www.flashgap.com/)."
25  * Alternately, this acknowlegement may appear in the software itself,
26  * if and wherever such third-party acknowlegements normally appear.
27  *
28  * 4. The name "The JGenerator" must not be used to endorse or promote
29  * products derived from this software without prior written permission.
30  * For written permission, please contact skavish@usa.net.
31  *
32  * 5. Products derived from this software may not be called "The JGenerator"
33  * nor may "The JGenerator" appear in their names without prior written
34  * permission of Dmitry Skavish.
35  *
36  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39  * DISCLAIMED. IN NO EVENT SHALL DMITRY SKAVISH OR THE OTHER
40  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
42  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
43  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
44  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
45  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
46  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47  * SUCH DAMAGE.
48  *
49  */

50
51 package org.openlaszlo.iv.flash.api.text;
52
53 import org.openlaszlo.iv.flash.parser.Parser;
54 import org.openlaszlo.iv.flash.util.*;
55 import org.openlaszlo.iv.flash.cache.*;
56
57 import org.openlaszlo.iv.flash.api.*;
58 import java.io.*;
59 import java.awt.geom.Rectangle2D JavaDoc;
60
61 /**
62  * Instance of Font in particular flash file.
63  * <p>
64  * There may be several instances of one font in one file.
65  *
66  * @author Dmitry Skavish
67  */

68 public final class FontDef extends FlashDef {
69
70     private boolean isWriteLayout = false; // if true - write font outlines as well
71
private boolean isWriteAllChars = false; // if true - write full set of characters, otherwise only used ones
72
private Font font; // font
73
private IVVector textBlocks = new IVVector(); // vector of TextBlock's using this font
74

75     /**
76      * Creates empty font definition
77      */

78     public FontDef() {
79     }
80
81     /**
82      * Creates font definition of specified font and ID
83      *
84      * @param font specified font
85      * @param id ID of font definition to be created
86      */

87     public FontDef( Font font, int id ) {
88         this.font = font;
89         setID( id );
90     }
91
92     public int getTag() {
93         return Tag.DEFINEFONT2;
94     }
95
96     /**
97      * Returns font name
98      *
99      * @return font name
100      */

101     public String JavaDoc getFontName() {
102         return font.fontName;
103     }
104
105     /**
106      * Returns font
107      *
108      * @return font
109      */

110     public Font getFont() {
111         return font;
112     }
113
114     public void setFont( Font font ) {
115         this.font = font;
116     }
117
118     /**
119      * Adds specified text block to this fontdef
120      *
121      * @param tblock specified text block
122      */

123     public void addTextBlock( TextBlock tblock ) {
124         if( tblock == null ) return;
125         textBlocks.addElement(tblock);
126     }
127
128     /**
129      * Adds vector of text blocks to this fontdef
130      *
131      * @param tblocks vector of text blocks
132      */

133     public void addTextBlocks( IVVector tblocks ) {
134         if( tblocks == null ) return;
135         for( int i=0; i<tblocks.size(); i++ ) {
136             addTextBlock( (TextBlock) tblocks.elementAt(i) );
137         }
138     }
139
140     /**
141      * Returns all text blocks added to this fontdef
142      *
143      * @return all text blocks added to this fontdef
144      */

145     public IVVector getTextBlocks() {
146         return textBlocks;
147     }
148
149     /**
150      * Specifies whether to write layout information when generating this font or not
151      *
152      * @param v true - write layout
153      */

154     public void setWriteLayout( boolean v ) {
155         isWriteLayout = v;
156     }
157
158     /**
159      * Returns true if layout information is going to generated
160      *
161      * @return true if layout information is going to generated
162      */

163     public boolean isWriteLayout() {
164         return isWriteLayout;
165     }
166
167     /**
168      * Specifies whether to write all font's character or only used (in text blocks) ones.
169      *
170      * @param v true - write all characters
171      */

172     public void setWriteAllChars( boolean v ) {
173         isWriteAllChars = v;
174     }
175
176     /**
177      * Returns true if all font's character are going to be generated
178      *
179      * @return true if all font's character are going to be generated
180      */

181     public boolean isWriteAllChars() {
182         return isWriteAllChars;
183     }
184
185     /**
186      * Parses External font tag
187      */

188     public static FontDef parseExternalFontTag( Parser p ) {
189         int id = p.getUWord();
190         String JavaDoc fontFileName = p.getString();
191         Font font = load( fontFileName, p.getFile() );
192         if( font != null ) return new FontDef( font, id );
193         return null;
194     }
195
196     /**
197      * Loads external font to the specified file
198      */

199     public static Font load( String JavaDoc fontFileName, FlashFile file ) {
200         FlashFile fontFile;
201         try {
202             fontFile = file.addExternalFile( fontFileName, true );
203         } catch( IVException e ) {
204             Log.log(e);
205             // load default symbol file and pick first font from it
206
fontFile = file.getDefaultSymbolFile();
207         }
208         if( fontFile != null ) {
209             IVVector v = fontFile.getLocalFonts();
210             if( v.size() == 0 ) {
211                 Log.logRB( Resource.INVLEXTERNALFONT, new Object JavaDoc[] {fontFileName} );
212                 return null;
213             }
214             return (Font) v.elementAt(0);
215         }
216         return null;
217     }
218
219     /**
220      * Loads font from file (FFT)
221      *
222      * @param fontFileName font file name
223      * @return loaded font
224      */

225     public static Font load( String JavaDoc fontFileName ) {
226         FlashFile fontFile;
227
228         // Find the font
229
fontFileName = Util.translatePath( fontFileName );
230         File f = new File( fontFileName );
231         if( !f.exists() ) {
232             fontFileName = Util.concatFileNames( PropertyManager.fontPath, fontFileName );
233             f = new File( Util.getInstallDir(), fontFileName );
234             if ( !f.exists() ) {
235                 Log.logRB( Resource.FILENOTFOUND, new Object JavaDoc[] {fontFileName} );
236                 return null;
237             }
238         }
239         fontFileName = f.getAbsolutePath();
240
241         // Load the font
242
try {
243             fontFile = FlashFile.parse( fontFileName );
244             IVVector v = fontFile.getLocalFonts();
245             if ( v.size() == 0 ) {
246                 Log.logRB( Resource.INVLEXTERNALFONT, new Object JavaDoc[] {fontFileName} );
247                 return null;
248             }
249             return (Font) v.elementAt(0);
250         } catch( FileNotFoundException e ) {
251             Log.logRB(Resource.FILENOTFOUND, new Object JavaDoc[] {fontFileName});
252             return null;
253         } catch( IVException e ) {
254             Log.log(e);
255             return null;
256         }
257     }
258
259     /**
260      * Parses DefineFont tag.
261      * <P>
262      * We expect that after DefineFont tag, DefineFontInfo tag will follow
263      * which will define codetable for this font.<br>
264      * This is not always true of course, but in majority of cases it is.
265      *
266      * @param p parser
267      * @return font def
268      */

269     public static FontDef parse( Parser p ) {
270         // get id
271
int id = p.getUWord();
272         Font font = new Font();
273         font.flags = Font.ANSI;
274         font.fileBuffer = p.getBuf();
275
276         // get offset table and shape table
277
int tableOffset = p.getPos();
278         int offset = p.getUWord();
279         int nGlyph = offset/2;
280
281         int[] glyphOffsets = new int[nGlyph+1]; // +1 because we need last offset
282
glyphOffsets[0] = tableOffset+offset;
283         for( int i=1; i<nGlyph; i++ ) glyphOffsets[i] = tableOffset+p.getUWord();
284
285         p.skipLastTag(); // skip all shapes
286
glyphOffsets[nGlyph] = p.getPos();
287
288         font.glyphOffsets = glyphOffsets;
289
290         // there is no need to cache font, fontinfo will take care of it
291
return new FontDef( font, id );
292     }
293
294     /**
295      * Parse DefineFontInfo tag
296      */

297     public static void parseFontInfoTag( Parser p, boolean MX ) {
298         // get id
299
int fontId = p.getUWord();
300         FontDef fontDef = (FontDef) p.getDef(fontId);
301         String JavaDoc fontName = p.getString( p.getUByte() );
302         int flags = (MX)? p.getUWord() : p.getUByte();
303         String JavaDoc ext = ((flags&0x04)!=0?"%i":"") + ((flags&0x02)!=0?"%b":"");
304         String JavaDoc fontKey = fontName+ext;
305
306         // do not put this font into cache
307
// later on we will try to merge it into some probably existing in cache font
308

309         Font font = fontDef.font;
310         font.fontName = fontName;
311         font.fontKey = fontKey;
312         font.flags = ((flags&0x04)!=0?Font.ITALIC:0) | ((flags&0x02)!=0?Font.BOLD:0) |
313                       ((flags&0x20)!=0?Font.UNICODE:0) | ((flags&0x10)!=0?Font.SHIFT_JIS:0) |
314                       ((flags&0x08)!=0?Font.ANSI:0) | ((flags&0x01)!=0?Font.WIDE_CODES:0);
315         //Log.logRB( Resource.STR, "parseInfo: font="+fontName+", font2="+font2+", flags="+Util.w2h(font.flags) );
316
// get code table
317
int nGlyph = font.getNumGlyph();
318         int[] codeTable = new int[nGlyph];
319         if( (font.flags&Font.WIDE_CODES) != 0 ) {
320             for( int i=0; i<nGlyph; i++ ) codeTable[i] = p.getUWord();
321         } else {
322             for( int i=0; i<nGlyph; i++ ) codeTable[i] = p.getUByte();
323         }
324         font.codeTable = codeTable;
325
326         // find 'blank'
327
for( int i=0; i<nGlyph; i++ ) {
328             if( codeTable[i] == ' ' ) {
329                 font.blankPos = i;
330                 break;
331             }
332         }
333     }
334
335     /**
336      * Parse DefineFontInfo tag
337      */

338     public static void parseFontInfoTag( Parser p ) {
339         parseFontInfoTag( p, false );
340     }
341
342     /**
343      * Parse DefineFontInfo2 tag
344      */

345     public static void parseFontInfoTag2( Parser p ) {
346         parseFontInfoTag( p, true );
347     }
348
349     /**
350      * Parse DefineFont2 tag
351      */

352     public static FontDef parse2( Parser p ) {
353         // get id
354
int id = p.getUWord();
355         // get flags
356
int flags = p.getUWord();
357         // get name of the font
358
String JavaDoc fontName = p.getString( p.getUByte() );
359
360         // check if this font is in cache
361
String JavaDoc ext = ((flags&Font.ITALIC)!=0?"%i":"")+((flags&Font.BOLD)!=0?"%b":"");
362         String JavaDoc fontKey = fontName+ext;
363         /* NOTE LASZLO: [2003-09-22 bloch] disable font cache (see bug 2109) */
364         /*
365         Font font2 = FontCache.getFont( fontKey );
366         */

367         Font font2 = null;
368
369         // get offset table and shape table
370
int nGlyph = p.getUWord();
371
372         // if these fonts have the same number of glyphs and the same flags then
373
// we guess that this is the same font and don't parse it further
374
// (we may be wrong, but it's very unlikely)
375
if( font2 != null ) {
376             if( nGlyph == font2.getNumGlyph() && flags == font2.flags ) {
377                 return new FontDef( font2, id );
378             }
379         }
380
381         Font font = new Font();
382         font.flags = flags;
383         font.fontName = fontName;
384         font.fontKey = fontKey;
385         font.fileBuffer = p.getBuf();
386         int tableOffset = p.getPos();
387         int[] glyphOffsets = new int[nGlyph+1]; // +1 because we need last offset
388
int codeOff;
389         if( (flags&Font.WIDE_OFFSETS) != 0 ) {
390             for( int i=0; i<nGlyph; i++ ) glyphOffsets[i] = tableOffset+p.getUDWord();
391             codeOff = p.getUDWord();
392         } else {
393             for( int i=0; i<nGlyph; i++ ) glyphOffsets[i] = tableOffset+p.getUWord();
394             codeOff = p.getUWord();
395         }
396         font.glyphOffsets = glyphOffsets;
397
398         // do not parse shapes, delay until we really need them
399
p.setPos( tableOffset+codeOff ); // skip shapes
400
glyphOffsets[nGlyph] = p.getPos();
401
402         // get code table
403
int[] codeTable = new int[nGlyph];
404         if( (flags&Font.WIDE_CODES) != 0 ) {
405             for( int i=0; i<nGlyph; i++ ) codeTable[i] = p.getUWord();
406         } else {
407             for( int i=0; i<nGlyph; i++ ) codeTable[i] = p.getUByte();
408         }
409         font.codeTable = codeTable;
410
411         // find 'blank'
412
for( int i=0; i<nGlyph; i++ ) {
413             if( codeTable[i] == ' ' ) {
414                 font.blankPos = i;
415                 break;
416             }
417         }
418
419         if( (flags&Font.HAS_LAYOUT) != 0 ) {
420             font.ascent = p.getWord();
421             font.descent = p.getWord();
422             font.leading = p.getWord();
423
424             // get advance table
425
int[] advanceTable = new int[nGlyph];
426             for( int i=0; i<nGlyph; i++ ) advanceTable[i] = p.getWord();
427             font.advanceTable = advanceTable;
428
429             // skip bounds table, delay until we need them
430
font.boundsBuffer = p.getBuf();
431             font.boundsOffset = p.getPos();
432             for( int i=0; i<nGlyph; i++ ) p.skipRect();
433             font.boundsLength = p.getPos()-font.boundsOffset;
434
435             // get kerning table
436
int nKern = p.getUWord();
437             font.kernLeftCodes = new int[nKern];
438             font.kernRightCodes = new int[nKern];
439             font.kernAdjustment = new int[nKern];
440             if( (flags&Font.WIDE_CODES) != 0 ) {
441                 for( int i=0; i<nKern; i++ ) {
442                     font.kernLeftCodes[i] = p.getUWord();
443                     font.kernRightCodes[i] = p.getUWord();
444                     font.kernAdjustment[i] = p.getWord();
445                 }
446             } else {
447                 for( int i=0; i<nKern; i++ ) {
448                     font.kernLeftCodes[i] = p.getUByte();
449                     font.kernRightCodes[i] = p.getUByte();
450                     font.kernAdjustment[i] = p.getWord();
451                 }
452             }
453         }
454
455         // cache only if there is no already such font in cache, font has a layout and number of
456
// glyphs >= 200
457
/* NOTE LASZLO: [2003-09-22 bloch] disable font cache (see bug 2109) */
458         /*
459         if( font2 == null && (flags&Font.HAS_LAYOUT) != 0 && nGlyph >= 200 ) {
460             FontCache.addFont( fontKey, font );
461         }
462         */

463
464         return new FontDef( font, id );
465     }
466
467     /**
468      * Builds and generates this font into buffer
469      *
470      * @param fob flash buffer
471      */

472     public void write( FlashOutput fob ) {
473
474         if (fob.defined( font )) {
475             return;
476         }
477
478         int pos = fob.getPos();
479         fob.skip(6);
480
481         fob.writeFontID( font );
482         if( isWriteLayout ) {
483             fob.writeWord( font.flags );
484         } else {
485             fob.writeWord( font.flags&~Font.HAS_LAYOUT );
486         }
487         fob.writeStringL( getFontName() );
488
489         // create index table
490
int[] indexTable = new int[font.codeTable.length];
491
492         // create codetable from registered text blocks
493
int[] codeTable;
494         int nGlyph;
495         if( isWriteAllChars ) {
496             codeTable = font.codeTable;
497             nGlyph = codeTable.length;
498             for( int i=0; i<indexTable.length; i++ ) indexTable[i] = i;
499         } else {
500             codeTable = new int[font.codeTable.length];
501             nGlyph = 0;
502         }
503
504         for( int i=0; i<textBlocks.size(); i++ ) {
505             TextBlock tblock = (TextBlock) textBlocks.elementAt(i);
506             tblock.layout();
507             IVVector trs = tblock.getTextRecords(font);
508             if( trs == null || trs.size() == 0 ) continue;
509             for( int t=0; t<trs.size(); t++ ) {
510                 TextRecord tr = (TextRecord) trs.elementAt(t);
511                 L1:
512                 for( int c=0; c<tr.getSize(); c++ ) {
513                     char ch = tr.getChar(c);
514                     if( ch == '\r' || ch == '\n' ) { // how come we see this chars here ?
515
tr.setIndex(c, 0); // ???
516
continue;
517                     }
518                     // find this char in our codetable
519
for( int j=0; j<nGlyph; j++ ) {
520                         if( codeTable[j] == ch ) {
521                             tr.setIndex(c, j);
522                             continue L1;
523                         }
524                     }
525                     // char has not been not found, add it
526
if( !isWriteAllChars ) { // should always be true here!
527
int idx = font.getIndex(ch); // get original index
528
if( idx == -1 ) {
529                             idx = font.getIndex(' ');
530                         }
531                         indexTable[nGlyph] = idx;
532                         tr.setIndex(c, nGlyph);
533                         codeTable[nGlyph] = ch;
534                         ++nGlyph;
535                     }
536                 }
537             }
538         }
539
540         fob.writeWord(nGlyph);
541         int offsetTable = fob.getPos();
542         int inc = (font.flags&Font.WIDE_OFFSETS)!=0? 4: 2;
543         fob.skip( nGlyph*inc );
544         int codeOffset = fob.getPos();
545         fob.skip( inc );
546         for( int i=0, curOff=offsetTable; i<nGlyph; i++, curOff+=inc ) {
547             int offset = fob.getPos()-offsetTable;
548             int idx = indexTable[i];
549             int start = font.glyphOffsets[idx];
550             int end = font.glyphOffsets[idx+1];
551             fob.writeArray( font.fileBuffer, start, end-start );
552             if( inc == 2 )
553                 fob.writeWordAt( offset, curOff );
554             else
555                 fob.writeDWordAt( offset, curOff );
556         }
557         if( inc == 2 )
558             fob.writeWordAt(fob.getPos()-offsetTable, codeOffset);
559         else
560             fob.writeDWordAt(fob.getPos()-offsetTable, codeOffset);
561
562         for( int i=0; i<nGlyph; i++ ) {
563             if( (font.flags&Font.WIDE_CODES) != 0 ) {
564                 fob.writeWord( codeTable[i] );
565             } else {
566                 fob.writeByte( codeTable[i] );
567             }
568         }
569
570         // write layout
571
if( isWriteLayout && ((font.flags&Font.HAS_LAYOUT) != 0) ) {
572             fob.writeWord( font.ascent );
573             fob.writeWord( font.descent );
574             fob.writeWord( font.leading );
575
576             // write advance table
577
for( int i=0; i<nGlyph; i++ ) fob.writeWord( font.advanceTable[indexTable[i]] );
578
579             // copy bounds table
580
if( isWriteAllChars ) {
581                 // just for the sake of perfomance, because font.getGlyphBounds() causes parsing of all bounds
582
fob.writeArray( font.boundsBuffer, font.boundsOffset, font.boundsLength );
583             } else {
584                 Rectangle2D JavaDoc[] bounds = font.getGlyphBounds();
585                 for( int i=0; i<nGlyph; i++ ) {
586                     fob.write( bounds[indexTable[i]] );
587                 }
588             }
589
590             // write kerning tables
591
// probably we need to restrict writing only to codes from codetable
592
int nKern = font.kernLeftCodes.length;
593             fob.writeWord( nKern );
594             if( (font.flags&Font.WIDE_CODES) != 0 ) {
595                 for( int i=0; i<nKern; i++ ) {
596                     fob.writeWord( font.kernLeftCodes[i] );
597                     fob.writeWord( font.kernRightCodes[i] );
598                     fob.writeWord( font.kernAdjustment[i] );
599                 }
600             } else {
601                 for( int i=0; i<nKern; i++ ) {
602                     fob.writeByte( font.kernLeftCodes[i] );
603                     fob.writeByte( font.kernRightCodes[i] );
604                     fob.writeWord( font.kernAdjustment[i] );
605                 }
606             }
607         }
608
609         fob.writeLongTagAt(Tag.DEFINEFONT2, fob.getPos()-pos-6, pos);
610     }
611
612     /**
613      * Merge two fonts
614      *
615      * @param f1 font to merge
616      * @param f2 font to merge
617      * @return new merged font
618      */

619     public static Font mergeFonts( Font f1, Font f2 ) {
620         //System.out.println( "Merging fonts: "+f2.getFontName() );
621
int flags = f2.flags | f1.flags;
622         //System.out.println( "f2_flags: "+Util.w2h(f2.flags)+", f1_flags: "+Util.w2h(f2.flags) );
623

624         boolean f1_hasLayout = (f1.flags&Font.HAS_LAYOUT) != 0;
625         boolean f2_hasLayout = (f2.flags&Font.HAS_LAYOUT) != 0;
626         if( f1_hasLayout && !f2_hasLayout ) {
627             Font f = f1; f1 = f2; f2 = f;
628             boolean fb = f1_hasLayout; f1_hasLayout = f2_hasLayout; f2_hasLayout = fb;
629         }
630
631         // merge code tables
632
int[] codeTable1 = f1.codeTable;
633         int[] codeTable2 = f2.codeTable;
634         int n = 0;
635         int[] codeTable_tmp = new int[codeTable1.length];
636         int[] indexes = new int[codeTable1.length];
637         for( int i=0; i<codeTable1.length; i++ ) {
638             int code = codeTable1[i];
639             int j=0;
640             for( ; j<codeTable2.length; j++ ) {
641                 if( codeTable2[j] == code ) break;
642             }
643             if( j == codeTable2.length ) {
644                 codeTable_tmp[n] = code;
645                 indexes[n] = i;
646                 n++;
647             }
648         }
649
650         if( n == 0 ) { // no new characters in f1
651
f2.copyTo(f1); // no need!!!
652
return f2;
653         }
654         //System.out.println( "continue merge" );
655

656         int nGlyph = codeTable2.length+n;
657         int[] codeTable = new int[nGlyph];
658         System.arraycopy( codeTable2, 0, codeTable, 0, codeTable2.length );
659         System.arraycopy( codeTable_tmp, 0, codeTable, codeTable2.length, n );
660
661         // merge glyphs
662
int f1_start = f1.glyphOffsets[0];
663         int f1_end = f1.glyphOffsets[codeTable1.length];
664         int f2_start = f2.glyphOffsets[0];
665         int f2_end = f2.glyphOffsets[codeTable2.length];
666         int totalSize = f1_end-f1_start + f2_end-f2_start;
667         byte[] fileBuffer = new byte[ totalSize ];
668         int[] glyphOffsets = new int[ nGlyph + 1 ];
669         int offset = f2_end-f2_start;
670         // copy glyphoffset and shapes from f2
671
System.arraycopy( f2.fileBuffer, f2_start, fileBuffer, 0, offset );
672         int gln = 0;
673         for( ; gln<codeTable2.length; gln++ ) {
674             int off = f2.glyphOffsets[gln] - f2_start;
675             glyphOffsets[gln] = off;
676         }
677         // copy glyphoffsets and shapes from f1
678
for( int i=0; i<n; i++, gln++ ) {
679             int idx = indexes[i];
680             int start = f1.glyphOffsets[idx];
681             int end = f1.glyphOffsets[idx+1];
682             int size = end-start;
683             System.arraycopy( f1.fileBuffer, start,
684                               fileBuffer, offset, size );
685             glyphOffsets[gln] = offset;
686             offset += size;
687         }
688         glyphOffsets[gln] = offset;
689
690         int[] advanceTable = null;
691         int[] kernLeftCodes = f2.kernLeftCodes;
692         int[] kernRightCodes = f2.kernRightCodes;
693         int[] kernAdjustment = f2.kernAdjustment;
694         // 2 cases:
695
// - no fonts have layouts
696
// - at least f2 has layout
697
if( f1_hasLayout || f2_hasLayout ) {
698             if( f1_hasLayout ) {
699                 // merge two layouts
700
// extend advancetable and boundstable
701
advanceTable = new int[nGlyph];
702                 int off = codeTable2.length;
703                 System.arraycopy( f2.advanceTable, 0, advanceTable, 0, off );
704                 for( int i=0; i<n; i++, off++ ) {
705                     int idx = indexes[i];
706                     int adv = f1.advanceTable[idx];
707                     advanceTable[off] = adv;
708                 }
709             } else {
710                 // use f2 layout
711
// extend advancetable and boundstable
712
advanceTable = new int[nGlyph];
713                 System.arraycopy( f2.advanceTable, 0, advanceTable, 0, codeTable2.length );
714                 for( int i=codeTable2.length; i<nGlyph; i++ ) {
715                     advanceTable[i] = 500;
716                 }
717             }
718         }
719
720         synchronized(f2) {
721             // store new data to f2 font
722
for( int i=0; i<nGlyph; i++ ) {
723                 if( codeTable[i] == ' ' ) {
724                     f2.blankPos = i;
725                     break;
726                 }
727             }
728             f2.kernAdjustment = kernAdjustment;
729             f2.kernLeftCodes = kernLeftCodes;
730             f2.kernRightCodes = kernRightCodes;
731             f2.advanceTable = advanceTable;
732             f2.flags = flags;
733             f2.codeTable = codeTable;
734             f2.glyphOffsets = glyphOffsets;
735             f2.fileBuffer = fileBuffer;
736
737             // need to copy bounds buffer too !!!
738
// .....
739
// ....
740

741             f2.copyTo(f1); // no need !!!
742
}
743
744         return f2;
745     }
746
747     public void printContent( PrintStream out, String JavaDoc indent ) {
748         font.printContent(out, indent, getID());
749     }
750
751     public boolean isConstant() {
752         return true;
753     }
754
755     protected FlashItem copyInto( FlashItem item, ScriptCopier copier ) {
756         super.copyInto( item, copier );
757         ((FontDef)item).font = font;
758         ((FontDef)item).isWriteAllChars = isWriteAllChars;
759         ((FontDef)item).isWriteLayout = isWriteLayout;
760         // nothing else
761
return item;
762     }
763
764     public FlashItem getCopy( ScriptCopier copier ) {
765         return copyInto( new FontDef(), copier );
766     }
767
768     /**
769      * Change font in all specified records to new one
770      *
771      * @param records vector containing TextRecord and TextStyleChangeRecord
772      * @param new_font new font
773      */

774     public static void changeRecordsFont( IVVector records, Font old_font, Font new_font ) {
775         //System.out.println( "changeRecordsFont:" );
776
Font last_font = null;
777         for( int i=0; i<records.size(); i++ ) {
778             Object JavaDoc o = records.elementAt(i);
779             if( o instanceof TextRecord ) {
780                 if( last_font == old_font ) {
781                     ((TextRecord)o).updateIndexes(new_font);
782                 }
783             } else {
784                 TextStyleChangeRecord trs = (TextStyleChangeRecord) o;
785                 Font font = trs.getFont();
786                 if( font != null ) {
787                     last_font = font;
788                     if( last_font == old_font ) {
789                         trs.setFont(new_font);
790                     }
791                 }
792             }
793         }
794     }
795 }
796
Popular Tags