1 /*
2 Ming, an SWF output library
3 Copyright (C) 2002 Opaque Industries - http://www.opaque.net/
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20 /* $Id$ */
21
22 #ifndef __C2MAN__
23 #include <math.h>
24 #include <stdio.h>
25 #include <string.h>
26 #include <stdlib.h>
27 #endif
28
29 #include "font.h"
30 #include "method.h"
31 #include "utf8.h"
32 #include "character.h"
33 #include "error.h"
34 #include "movie.h"
35 #include "libming.h"
36 #include "shape.h"
37 #include "fdbfont.h"
38 #include "ttffont.h"
39 #include "ming_config.h"
40
41 struct textList
42 {
43 struct textList* next;
44 SWFTextRecord text;
45 };
46
47 struct SWFFontCharacter_s
48 {
49 struct SWFCharacter_s character;
50
51 SWFFont font;
52 byte flags;
53
54 /* add all font charactes. usefull for textfield */
55 byte dump;
56
57 // list of text records that reference this font
58 struct textList* textList;
59 struct textList* currentList;
60
61 // list of chars used in text objects that reference this font-
62 // idx into this table is stored in text records
63 int nGlyphs;
64 unsigned short* codeTable;
65
66 SWFOutput out;
67 };
68
69 void
SWFFont_buildReverseMapping(SWFFont font)70 SWFFont_buildReverseMapping(SWFFont font)
71 {
72 int i;
73
74 if ( font->flags & SWF_FONT_WIDECODES )
75 {
76 font->codeToGlyph.wideMap = (unsigned short**)malloc(256 * sizeof(unsigned short*));
77
78 for ( i=0; i<256; ++i )
79 font->codeToGlyph.wideMap[i] = NULL;
80
81 for ( i=0; i<font->nGlyphs; ++i )
82 {
83 unsigned short charcode = font->glyphToCode[i];
84 byte high = charcode >> 8;
85 byte low = charcode & 0xff;
86
87 if ( font->codeToGlyph.wideMap[high] == NULL )
88 {
89 font->codeToGlyph.wideMap[high] = (unsigned short*)malloc(256 * sizeof(unsigned short));
90 memset(font->codeToGlyph.wideMap[high], 0, 256 * sizeof(unsigned short));
91 }
92
93 font->codeToGlyph.wideMap[high][low] = i;
94 }
95 }
96 else
97 {
98 font->codeToGlyph.charMap = (byte*) malloc(256 * sizeof(char));
99 memset(font->codeToGlyph.charMap, 0, 256 * sizeof(char));
100
101 for ( i=0; i<font->nGlyphs; ++i )
102 {
103 if (font->glyphToCode[i]<256)
104 font->codeToGlyph.charMap[font->glyphToCode[i]] = i;
105 else
106 SWF_warn("No such glyph %d in map\n",i);
107 }
108 }
109 }
110
111 static void
112 SWFFontCharacter_resolveTextCodes(SWFFontCharacter);
113
114 static void
115 SWFFontCharacter_dumpTable(SWFFontCharacter);
116
117 static int
completeSWFFontCharacter(SWFBlock block)118 completeSWFFontCharacter(SWFBlock block)
119 {
120 SWFFontCharacter inst = (SWFFontCharacter)block;
121 SWFFont font = inst->font;
122 SWFOutput buffer;
123 int i, tablen, offset;
124 char c, *string;
125
126 if(inst->dump)
127 SWFFontCharacter_dumpTable(inst);
128 else
129 SWFFontCharacter_resolveTextCodes(inst);
130
131 SWF_assert(!inst->out);
132 inst->out = newSWFOutput();
133 SWFOutput_writeUInt16(inst->out, CHARACTERID(inst));
134 SWFOutput_writeUInt8(inst->out, inst->flags);
135 SWFOutput_writeUInt8(inst->out, font->langCode);
136
137 SWFOutput_writeUInt8(inst->out, strlen(font->name));
138 string = font->name;
139 while ( (c = *(string++)) != 0 )
140 SWFOutput_writeUInt8(inst->out, c);
141
142 SWFOutput_writeUInt16(inst->out, inst->nGlyphs);
143
144 tablen = (inst->nGlyphs+1) *
145 (inst->flags & SWF_FONT_WIDEOFFSETS ? 4 : 2);
146 buffer = newSWFOutput();
147 for (i = 0; i < inst->nGlyphs; ++i)
148 {
149 int glyph = SWFFont_findGlyphCode(font,inst->codeTable[i]);
150 SWFShape shape = font->shapes[glyph];
151 offset = SWFOutput_getLength(buffer) + tablen;
152 SWFOutput_writeGlyphShape(buffer, shape);
153 if(inst->flags & SWF_FONT_WIDEOFFSETS)
154 SWFOutput_writeUInt32(inst->out, offset);
155 else
156 SWFOutput_writeUInt16(inst->out, offset);
157 }
158 // codeTableOffset
159 offset = SWFOutput_getLength(buffer) + tablen;
160 if(inst->flags & SWF_FONT_WIDEOFFSETS)
161 SWFOutput_writeUInt32(inst->out, offset);
162 else
163 SWFOutput_writeUInt16(inst->out, offset);
164
165 /* user buffer from here! */
166 SWFOutput_setNext(inst->out, buffer);
167
168 for (i = 0; i < inst->nGlyphs; ++i)
169 {
170 unsigned short code = inst->codeTable[i];
171 if (inst->flags & SWF_FONT_WIDECODES)
172 SWFOutput_writeUInt16(buffer, code);
173 else
174 SWFOutput_writeUInt8(buffer, code);
175 }
176
177 /* write font layout */
178 if (inst->flags & SWF_FONT_HASLAYOUT )
179 { SWFOutput_writeUInt16(buffer, font->ascent);
180 SWFOutput_writeUInt16(buffer, font->descent);
181 SWFOutput_writeUInt16(buffer, font->leading);
182 for (i = 0; i < inst->nGlyphs; ++i) {
183 int glyph = SWFFont_findGlyphCode(font,inst->codeTable[i]);
184 SWFOutput_writeSInt16(buffer,font->advances[glyph]);
185 }
186 for (i = 0; i < inst->nGlyphs; ++i) {
187 int glyph = SWFFont_findGlyphCode(font,inst->codeTable[i]);
188 SWFOutput_writeRect(buffer, SWFFont_getGlyphBounds(font, glyph));
189 SWFOutput_byteAlign(buffer);
190 }
191 SWFOutput_writeUInt16(buffer, 0); /* no kerning FIXME ! */
192 }
193 return SWFOutput_getLength(inst->out);
194 }
195
196
197 void
writeSWFFontCharacterToMethod(SWFBlock block,SWFByteOutputMethod method,void * data)198 writeSWFFontCharacterToMethod(SWFBlock block,
199 SWFByteOutputMethod method, void *data)
200 {
201 SWFFontCharacter inst = (SWFFontCharacter)block;
202 SWFOutput_writeToMethod(inst->out, method, data);
203 }
204
205
206 void
destroySWFFont(SWFFont font)207 destroySWFFont(SWFFont font)
208 {
209 if(font->shapes)
210 {
211 int i = 0;
212 for(i = 0; i < font->nGlyphs; i++)
213 destroySWFShape(font->shapes[i]);
214 free(font->shapes);
215 }
216
217 if ( font->flags & SWF_FONT_WIDECODES )
218 {
219 if ( font->codeToGlyph.wideMap != NULL )
220 {
221 int i;
222
223 for ( i = 0; i < 256; ++i )
224 {
225 if ( font->codeToGlyph.wideMap[i] != NULL )
226 free(font->codeToGlyph.wideMap[i]);
227 }
228
229 free(font->codeToGlyph.wideMap);
230 }
231 }
232 else
233 {
234 if ( font->codeToGlyph.charMap != NULL )
235 free(font->codeToGlyph.charMap);
236 }
237
238 if ( font->name != NULL )
239 free(font->name);
240
241 if ( font->kernTable.k != NULL ) // union of pointers ...
242 free(font->kernTable.k);
243
244 if ( font->glyphToCode != NULL )
245 free(font->glyphToCode);
246
247 if ( font->advances != NULL )
248 free(font->advances);
249
250 free(font);
251 }
252
253
254 void
destroySWFFontCharacter(SWFFontCharacter font)255 destroySWFFontCharacter(SWFFontCharacter font)
256 {
257 struct textList* text = font->textList;
258
259 while ( text != NULL )
260 {
261 struct textList* next = text->next;
262 free(text);
263 text = next;
264 }
265
266 if ( font->codeTable != NULL )
267 free(font->codeTable);
268 if( font->out != NULL)
269 destroySWFOutput(font->out);
270 free(font);
271 }
272
273
274 SWFFont
newSWFFont()275 newSWFFont()
276 {
277 SWFFont font = (SWFFont) malloc(sizeof(struct SWFFont_s));
278
279 SWFBlockInit((SWFBlock)font);
280
281 BLOCK(font)->type = SWF_MINGFONT;
282 BLOCK(font)->writeBlock = NULL;
283 BLOCK(font)->complete = NULL;
284 BLOCK(font)->dtor = (destroySWFBlockMethod) destroySWFFont;
285
286 font->name = NULL;
287 font->flags = 0;
288 font->langCode = 0;
289
290 font->nGlyphs = 0;
291 font->glyphToCode = NULL;
292
293 font->advances = NULL;
294
295 font->ascent = 0;
296 font->descent = 0;
297 font->leading = 0;
298
299 font->kernCount = 0;
300 font->kernTable.k = NULL;
301 font->kernTable.w = NULL;
302
303 font->shapes = NULL;
304
305 return font;
306 }
307
308 // file magic: fonts:0 string \000\001\000\000\000 TrueType font data
true_type_check(char * header)309 static inline int true_type_check(char *header)
310 {
311 if(header[0] == 0 &&
312 header[1] == 1 &&
313 header[2] == 0 &&
314 header[3] == 0 &&
315 header[4] == 0)
316 return 1;
317 return 0;
318 }
319
fdb_check(char * header)320 static inline int fdb_check(char *header)
321 {
322 if(header[0] == 'f' &&
323 header[1] == 'd' &&
324 header[2] == 'b' &&
325 header[3] == '0')
326 return 1;
327 return 0;
328 }
329
ttc_check(char * header)330 static inline int ttc_check(char *header)
331 {
332 if(header[0] == 't' &&
333 header[1] == 't' &&
334 header[2] == 'c')
335 return 1;
336 return 0;
337 }
338
339 /* load a collection of fonts (experimental)
340 * currently only TTC (TTF collection) format is supported
341 */
newSWFFontCollection_fromFile(const char * filename)342 SWFFontCollection newSWFFontCollection_fromFile(const char *filename /* filename */)
343 {
344 FILE *file;
345 char header[5];
346 file = fopen(filename, "rb");
347 if(file == NULL)
348 {
349 SWF_warn("open font file failed\n");
350 return NULL;
351 }
352
353 if(fread(header, 5, 1, file) < 1)
354 {
355 fclose(file);
356 return NULL;
357 }
358 rewind(file);
359
360 if(ttc_check(header))
361 {
362 fclose(file);
363 #if USE_FREETYPE
364 return loadTTFCollection(filename);
365 #else
366 SWF_warn("SWFFont:: new SWFFont (ttf): "
367 "freetype is not available.\n");
368 return NULL;
369 #endif
370 }
371 else
372 {
373 SWF_warn("Unknown font file\n");
374 fclose(file);
375 return NULL;
376 }
377 }
378
379
380 /* load a font from file
381 * This function creates a new SWFFont object from a font file. It accepts
382 * and autodetects FDB and TTF fonts.
383 * returns a SWFFont object if a valid fontfile is found, NULL otherwise
384 */
newSWFFont_fromFile(const char * filename)385 SWFFont newSWFFont_fromFile(const char *filename /* filename for fontfile */)
386 {
387 FILE *file;
388 char header[5];
389 file = fopen(filename, "rb");
390 if(file == NULL)
391 {
392 SWF_warn("open font file failed\n");
393 return NULL;
394 }
395
396 if(fread(header, 5, 1, file) < 1)
397 {
398 fclose(file);
399 return NULL;
400 }
401 rewind(file);
402
403 if(true_type_check(header))
404 {
405 fclose(file);
406 #if USE_FREETYPE
407 return loadSWFFontTTF(filename);
408 #else
409 SWF_warn("SWFFont:: new SWFFont (ttf): "
410 "freetype is not available.\n");
411 return NULL;
412 #endif
413 }
414 else if(fdb_check(header))
415 {
416 SWFFont font = loadSWFFont_fromFdbFile(file);
417 fclose(file);
418 return font;
419 }
420 else
421 {
422 SWF_warn("Unknown font file\n");
423 fclose(file);
424 return NULL;
425 }
426 }
427
428
429 SWFFontCharacter
newSWFFontCharacter(SWFFont font)430 newSWFFontCharacter(SWFFont font)
431 {
432 SWFFontCharacter inst;
433
434 inst = (SWFFontCharacter) malloc(sizeof(struct SWFFontCharacter_s));
435 SWFCharacterInit((SWFCharacter)inst);
436
437 BLOCK(inst)->type = SWF_DEFINEFONT2;
438 BLOCK(inst)->writeBlock = writeSWFFontCharacterToMethod;
439 BLOCK(inst)->complete = completeSWFFontCharacter;
440 BLOCK(inst)->dtor = (destroySWFBlockMethod) destroySWFFontCharacter;
441
442 CHARACTERID(inst) = ++SWF_gNumCharacters;
443 inst->font = font;
444 inst->flags = font->flags; // (unsigned char)(font->flags & /*(~SWF_FONT_HASLAYOUT) &*/ (~SWF_FONT_WIDEOFFSETS));
445
446 inst->nGlyphs = 0;
447 inst->codeTable = NULL;
448 inst->dump = 0;
449 inst->textList = NULL;
450 inst->currentList = NULL;
451
452 inst->out = NULL;
453
454 return inst;
455 }
456
457 SWFFontCharacter
newSWFDummyFontCharacter()458 newSWFDummyFontCharacter()
459 { SWFFontCharacter ret = (SWFFontCharacter) malloc(sizeof (struct SWFFontCharacter_s));
460 SWFCharacterInit((SWFCharacter) ret);
461 BLOCK(ret)->type = SWF_DEFINEFONT;
462 BLOCK(ret)->complete = completeSWFImportCharacter;
463 BLOCK(ret)->writeBlock = NULL;
464 BLOCK(ret)->dtor = NULL;
465 CHARACTERID(ret) = ++SWF_gNumCharacters;
466
467 ret->flags = SWF_FONT_HASLAYOUT;
468 ret->nGlyphs = 1;
469 ret->codeTable = NULL;
470 ret->out = NULL;
471
472 return ret;
473 }
474
475 int
SWFFont_findGlyphCode(SWFFont font,unsigned short c)476 SWFFont_findGlyphCode(SWFFont font, unsigned short c)
477 {
478 if ( font->flags & SWF_FONT_WIDECODES )
479 {
480 byte high = c >> 8;
481 byte low = c & 0xff;
482
483 if ( font->codeToGlyph.wideMap[high] != NULL )
484 return font->codeToGlyph.wideMap[high][low];
485 else
486 return -1;
487 }
488 else
489 {
490 if ( (c & 0xff00) == 0 )
491 return font->codeToGlyph.charMap[(byte)c];
492 else
493 return -1;
494 }
495 }
496
497 void
SWFFontCharacter_addTextToList(SWFFontCharacter font,SWFTextRecord text)498 SWFFontCharacter_addTextToList(SWFFontCharacter font, SWFTextRecord text)
499 {
500 struct textList* textList = (struct textList* )malloc(sizeof(struct textList));
501
502 textList->next = font->textList;
503 textList->text = text;
504
505 font->textList = textList;
506 }
507
508
509 static int
findCodeValue(unsigned short c,unsigned short * list,int start,int end)510 findCodeValue(unsigned short c, unsigned short* list, int start, int end)
511 {
512 int pos;
513
514 if ( start == end )
515 return start;
516
517 if ( c <= list[start] )
518 return start;
519
520 pos = (start + end) / 2;
521
522 if ( c < list[pos] )
523 return findCodeValue(c, list, start, pos);
524 else if ( c > list[pos] )
525 return findCodeValue(c, list, pos+1, end);
526 else
527 return pos;
528 }
529
530
531 #define CODETABLE_INCREMENT 32
532
533 void
SWFFontCharacter_addCharToTable(SWFFontCharacter font,unsigned short c)534 SWFFontCharacter_addCharToTable(SWFFontCharacter font, unsigned short c)
535 {
536 // insert the char into font's codeTable if it isn't already there
537
538 int p;
539
540 p = findCodeValue(c, font->codeTable, 0, font->nGlyphs);
541
542 if ( font->codeTable != NULL && p != font->nGlyphs && font->codeTable[p] == c )
543 return;
544
545 if ( font->nGlyphs % CODETABLE_INCREMENT == 0 )
546 {
547 font->codeTable = (unsigned short*) realloc(font->codeTable,
548 (font->nGlyphs + CODETABLE_INCREMENT) *
549 sizeof(unsigned short));
550 memset(font->codeTable+font->nGlyphs, 0,
551 CODETABLE_INCREMENT*sizeof(unsigned short));
552 }
553
554 // keep list sorted
555
556 if ( p < font->nGlyphs )
557 {
558 memmove(&font->codeTable[p + 1], &font->codeTable[p],
559 (font->nGlyphs - p) * sizeof(*font->codeTable));
560 }
561
562 font->codeTable[p] = c;
563 ++font->nGlyphs;
564 }
565
566 void
SWFFontCharacter_addWideChars(SWFFontCharacter font,unsigned short * string,int len)567 SWFFontCharacter_addWideChars(SWFFontCharacter font, unsigned short *string, int len)
568 {
569 while(--len >= 0)
570 SWFFontCharacter_addCharToTable(font, *string++);
571 }
572
573 /*
574 * add all utf-8 characters in the given string to the SWF file.
575 * The font-block in the resulting SWF file will include all the
576 * utf-8 characters in the given string.
577 */
578 void
SWFFontCharacter_addUTF8Chars(SWFFontCharacter font,const char * string)579 SWFFontCharacter_addUTF8Chars(SWFFontCharacter font, const char *string)
580 {
581 unsigned short *widestring;
582 int len;
583 len = UTF8ExpandString(string, &widestring);
584 SWFFontCharacter_addWideChars(font, widestring, len);
585 free(widestring);
586 }
587
588 /*
589 * add all characters in the given string to the SWF file.
590 * The font-block in the resulting SWF file will include all the
591 * characters in the given string.
592 */
593 void
SWFFontCharacter_addChars(SWFFontCharacter font,const char * string)594 SWFFontCharacter_addChars(SWFFontCharacter font, const char *string)
595 {
596 while(*string)
597 SWFFontCharacter_addCharToTable(font, *string++ & 0xff);
598 }
599
600 SWFFont
SWFFontCharacter_getFont(SWFFontCharacter font)601 SWFFontCharacter_getFont(SWFFontCharacter font)
602 {
603 return font->font;
604 }
605
606
607 void
SWFFontCharacter_exportCharacterRange(SWFFontCharacter font,unsigned short start,unsigned short end)608 SWFFontCharacter_exportCharacterRange(SWFFontCharacter font,
609 unsigned short start, unsigned short end)
610 {
611 // insert the char into font's codeTable if it isn't already there
612
613 //int p = findCodeValue(start, font->codeTable, 0, font->nGlyphs);
614 //int q = findCodeValue(end, font->codeTable, 0, font->nGlyphs);
615
616 // XXX
617 }
618
619
620 int
SWFFontCharacter_findGlyphCode(SWFFontCharacter font,unsigned short c)621 SWFFontCharacter_findGlyphCode(SWFFontCharacter font, unsigned short c)
622 {
623 // return the index in font->codeTable for the given character
624
625 int p = findCodeValue(c, font->codeTable, 0, font->nGlyphs);
626
627 if ( font->codeTable[p] == c )
628 return p;
629
630 return -1;
631 }
632
633 static void
SWFFontCharacter_dumpTable(SWFFontCharacter fc)634 SWFFontCharacter_dumpTable(SWFFontCharacter fc)
635 {
636 int i;
637 SWFFont font = fc->font;
638 for (i = 0; i < font->nGlyphs; ++i)
639 {
640 unsigned short charcode = font->glyphToCode[i];
641 SWFFontCharacter_addCharToTable(fc, charcode);
642 }
643 }
644
645 static void
SWFFontCharacter_resolveTextCodes(SWFFontCharacter font)646 SWFFontCharacter_resolveTextCodes(SWFFontCharacter font)
647 {
648 struct textList* text = font->textList;
649 unsigned short* string;
650 int len, i;
651
652 // find out which characters from this font are being used
653
654 while ( text != NULL )
655 {
656 len = SWFTextRecord_getString(text->text, &string);
657
658 for ( i=0; i<len; ++i )
659 SWFFontCharacter_addCharToTable(font, string[i]);
660
661 text = text->next;
662 }
663
664 // check availability of a font glyph for each fontchar codetable entry
665
666 for ( i=0; i<font->nGlyphs; ++i )
667 {
668 int code;
669 code = SWFFont_findGlyphCode(font->font, font->codeTable[i]);
670 if(code < 0)
671 {
672 SWF_warn("SWFFontCharacter_resolveTextCodes: Character not found %i\n",
673 font->codeTable[i]);
674 SWF_warn("This is either an encoding error (likely)");
675 SWF_warn("or the used font does not provide all characters (unlikely)\n");
676 SWF_error("Stopped\n");
677 }
678 }
679 }
680
681 /*
682 * adds all characters/glyphs to the SWF
683 * This function is usefull if an full export of the font is intended.
684 */
685 void
SWFFontCharacter_addAllChars(SWFFontCharacter fc)686 SWFFontCharacter_addAllChars(SWFFontCharacter fc)
687 {
688 fc->dump = 1;
689 }
690
691 const char*
SWFFont_getName(SWFFont font)692 SWFFont_getName(SWFFont font)
693 {
694 return (const char*) font->name;
695 }
696
697
698 byte
SWFFont_getFlags(SWFFont font)699 SWFFont_getFlags(SWFFont font)
700 {
701 return font->flags;
702 }
703
SWFFont_getGlyphCount(SWFFont font)704 int SWFFont_getGlyphCount(SWFFont font)
705 {
706 return font->nGlyphs;
707 }
708
709 int
SWFFontCharacter_getNGlyphs(SWFFontCharacter font)710 SWFFontCharacter_getNGlyphs(SWFFontCharacter font)
711 {
712 return font->nGlyphs;
713 }
714
715
716 int
SWFFont_getScaledWideStringWidth(SWFFont font,const unsigned short * string,int len)717 SWFFont_getScaledWideStringWidth(SWFFont font,const unsigned short* string, int len)
718 {
719 /* return length of given string in whatever units these are we're using */
720
721 int i;
722 int width = 0;
723 int glyph;
724
725 for ( i=0; i<len; ++i )
726 {
727 glyph = SWFFont_findGlyphCode(font, string[i]);
728
729 if ( glyph == -1 )
730 continue; // XXX - ???
731
732 if ( font->advances )
733 width += font->advances[glyph];
734
735 // looking in kernTable
736
737 if ( i < len-1 ) {
738 width += SWFFont_getCharacterKern(font, string[i], string[i+1]);
739 }
740 }
741
742 return width;
743 }
744
745
746 int
SWFFont_getScaledStringWidth(SWFFont font,const char * string)747 SWFFont_getScaledStringWidth(SWFFont font, const char* string)
748 {
749 unsigned short* widestr;
750 int len = strlen(string);
751 int n, width;
752 widestr = (unsigned short*) malloc(2 * len);
753 for(n = 0 ; n < len ; n++)
754 widestr[n] = (unsigned char)string[n];
755 width = SWFFont_getScaledWideStringWidth(font, widestr, len);
756 free(widestr);
757 return width;
758 }
759
760 int
SWFFont_getScaledUTF8StringWidth(SWFFont font,const char * string)761 SWFFont_getScaledUTF8StringWidth(SWFFont font, const char* string)
762 {
763 unsigned short* widestr;
764 int len = UTF8ExpandString(string, &widestr);
765 int width = SWFFont_getScaledWideStringWidth(font, widestr, len);
766
767 free(widestr);
768
769 return width;
770 }
771
772
773 /* get some font metrics */
774 short
SWFFont_getScaledAscent(SWFFont font)775 SWFFont_getScaledAscent(SWFFont font)
776 {
777 return font->ascent;
778 }
779
780
781 short
SWFFont_getScaledDescent(SWFFont font)782 SWFFont_getScaledDescent(SWFFont font)
783 {
784 return font->descent;
785 }
786
787
788 short
SWFFont_getScaledLeading(SWFFont font)789 SWFFont_getScaledLeading(SWFFont font)
790 {
791 return font->leading;
792 }
793
794
795 unsigned short
SWFFontCharacter_getGlyphCode(SWFFontCharacter font,unsigned short glyphcode)796 SWFFontCharacter_getGlyphCode(SWFFontCharacter font, unsigned short glyphcode)
797 {
798 if ( glyphcode >= font->nGlyphs )
799 SWF_error("SWFFontCharacter_getGlyphCode: No such row in codeTable");
800 return font->codeTable[glyphcode];
801 }
802
803 unsigned short
SWFFont_getGlyphCode(SWFFont font,unsigned short glyphcode)804 SWFFont_getGlyphCode(SWFFont font, unsigned short glyphcode)
805 {
806 if ( glyphcode >= font->nGlyphs )
807 SWF_error("SWFFont_getGlyphCode: glyphcode >= nGlyphs");
808
809 return font->glyphToCode[glyphcode];
810 }
811
812
813 SWFRect
SWFFont_getGlyphBounds(SWFFont font,unsigned short glyphcode)814 SWFFont_getGlyphBounds(SWFFont font, unsigned short glyphcode)
815 {
816 if ( glyphcode >= font->nGlyphs )
817 SWF_error("SWFFont_getGlyphBounds: glyphcode >= nGlyphs");
818
819 // return &font->bounds[glyphcode];
820 return SWFCharacter_getBounds(CHARACTER(font->shapes[glyphcode])); // &font->bounds[glyphcode];
821 }
822
823
824 int
SWFFont_getCharacterAdvance(SWFFont font,unsigned short glyphcode)825 SWFFont_getCharacterAdvance(SWFFont font, unsigned short glyphcode)
826 {
827 if ( font->advances )
828 {
829 if ( glyphcode >= font->nGlyphs )
830 SWF_error("SWFFont_getCharacterAdvance: glyphcode >= nGlyphs");
831
832 return font->advances[glyphcode];
833 }
834
835 return 0;
836 }
837
838
839 int
SWFFont_getCharacterKern(SWFFont font,unsigned short code1,unsigned short code2)840 SWFFont_getCharacterKern(SWFFont font, unsigned short code1, unsigned short code2)
841 {
842 int j = font->kernCount;
843
844 // XXX - kernTable should be sorted to make this faster
845
846 if(font->flags & SWF_FONT_WIDECODES) {
847 if( !font->kernTable.w ) {
848 return 0;
849 }
850 while ( --j >= 0 )
851 {
852 if ( code1 == font->kernTable.w[j].code1 &&
853 code2 == font->kernTable.w[j].code2 )
854 {
855 return font->kernTable.w[j].adjustment;
856 }
857 }
858 } else {
859 if( !font->kernTable.k ) {
860 return 0;
861 }
862 while ( --j >= 0 )
863 {
864 if ( code1 == font->kernTable.k[j].code1 &&
865 code2 == font->kernTable.k[j].code2 )
866 {
867 return font->kernTable.k[j].adjustment;
868 }
869 }
870 }
871 return 0;
872 }
873
SWFFont_getGlyph(SWFFont font,unsigned short c)874 SWFShape SWFFont_getGlyph(SWFFont font, unsigned short c)
875 {
876 int index;
877
878 index = SWFFont_findGlyphCode(font, c);
879 if(index < 0)
880 return NULL;
881
882 return font->shapes[index];
883 }
884
SWFFontCollection_addFont(SWFFontCollection collection,SWFFont font)885 void SWFFontCollection_addFont(SWFFontCollection collection, SWFFont font)
886 {
887 if(!collection || !font)
888 return;
889
890 collection->fontList = (SWFFont*)realloc(collection->fontList,
891 (collection->numFonts + 1) * sizeof(SWFFont));
892 collection->fontList[collection->numFonts] = font;
893 collection->numFonts++;
894 }
895
destroySWFFontCollection(SWFFontCollection collection)896 void destroySWFFontCollection(SWFFontCollection collection)
897 {
898 int i;
899 if(!collection)
900 return;
901
902 for(i = 0; i < collection->numFonts; i++)
903 destroySWFFont(collection->fontList[i]);
904 free(collection->fontList);
905 free(collection);
906 }
907
newSWFFontCollection()908 SWFFontCollection newSWFFontCollection()
909 {
910 SWFFontCollection collection;
911
912 collection = (SWFFontCollection) malloc(sizeof(struct SWFFontCollection_s));
913 collection->fontList = NULL;
914 collection->numFonts = 0;
915
916 return collection;
917 }
918
SWFFontCollection_getFontCount(SWFFontCollection collection)919 int SWFFontCollection_getFontCount(SWFFontCollection collection)
920 {
921 if(collection == NULL)
922 return -1;
923 return collection->numFonts;
924 }
925
SWFFontCollection_getFont(SWFFontCollection collection,int index)926 SWFFont SWFFontCollection_getFont(SWFFontCollection collection, int index)
927 {
928 if(index < 0 || index >= collection->numFonts)
929 return NULL;
930
931 return collection->fontList[index];
932 }
933
SWFFontCollection_getFonts(SWFFontCollection collection,int * count)934 SWFFont *SWFFontCollection_getFonts(SWFFontCollection collection, int *count)
935 {
936 if(!collection)
937 {
938 *count = 0;
939 return NULL;
940 }
941 *count = collection->numFonts;
942 return collection->fontList;
943 }
944
945 /*
946 * Local variables:
947 * tab-width: 2
948 * c-basic-offset: 2
949 * End:
950 */
951