5 Extension module for the rfxswf library.
6 Part of the swftools package.
8 Copyright (c) 2001 Rainer Böhme <rfxswf@reflex-studio.de>
9 Copyright (c) 2003,2004 Matthias Kramm
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2 of the License, or
14 (at your option) any later version.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
25 #include "../rfxswf.h"
27 U32 readUTF8char(U8 ** text)
30 if (!(*(*text) & 0x80))
33 /* 0000 0080-0000 07FF 110xxxxx 10xxxxxx */
34 if (((*text)[0] & 0xe0) == 0xc0 && (*text)[1]) {
35 c = ((*text)[0] & 0x1f) << 6 | ((*text)[1] & 0x3f);
39 /* 0000 0800-0000 FFFF 1110xxxx 10xxxxxx 10xxxxxx */
40 if (((*text)[0] & 0xf0) == 0xe0 && (*text)[1] && (*text)[2]) {
41 c = ((*text)[0] & 0x0f) << 12 | ((*text)[1] & 0x3f) << 6 | ((*text)[2] & 0x3f);
45 /* 0001 0000-001F FFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */
46 if (((*text)[0] & 0xf8) == 0xf0 && (*text)[1] && (*text)[2]
48 c = ((*text)[0] & 0x07) << 18 | ((*text)[1] & 0x3f) << 12 | ((*text)[2] & 0x3f) << 6 | ((*text)[3] & 0x3f);
52 /* 0020 0000-03FF FFFF 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx */
53 if (((*text)[0] & 0xfc) == 0xf8 && (*text)[1] && (*text)[2]
56 c = ((*text)[0] & 0x03) << 24 | ((*text)[1] & 0x3f) << 18 | ((*text)[2] & 0x3f) << 12 | ((*text)[3] & 0x3f) << 6 | ((*text)[4] & 0x3f);
60 /* 0400 0000-7FFF FFFF 1111110x 10xxxxxx ... 10xxxxxx */
61 if (((*text)[0] & 0xfe) == 0xfc && (*text)[1] && (*text)[2]
63 && (*text)[4] && (*text)[5]) {
64 c = ((*text)[0] & 0x01) << 30 | ((*text)[1] & 0x3f) << 24 |
65 ((*text)[2] & 0x3f) << 18 | ((*text)[3] & 0x3f) << 12 | ((*text)[4] & 0x3f) << 6 | ((*text)[5] & 0x3f) << 6;
72 #define TF_TEXTCONTROL 0x80
73 #define TF_HASFONT 0x08
74 #define TF_HASCOLOR 0x04
75 #define TF_HASYOFFSET 0x02
76 #define TF_HASXOFFSET 0x01
78 #define FF_WIDECODES 0x01
80 #define FF_ITALIC 0x04
82 #define FF_SHIFTJIS 0x10
83 #define FF_UNICODE 0x20
86 #define FF2_ITALIC 0x02
87 #define FF2_WIDECODES 0x04
88 #define FF2_WIDEOFFSETS 0x08
90 #define FF2_UNICODE 0x20
91 #define FF2_SHIFTJIS 0x40
92 #define FF2_LAYOUT 0x80
94 int swf_FontIsItalic(SWFFONT * f)
96 return f->style & FONT_STYLE_ITALIC;
99 int swf_FontIsBold(SWFFONT * f)
101 return f->style & FONT_STYLE_BOLD;
104 static const int WRITEFONTID = 0x4e46; // font id for WriteFont and ReadFont
106 int swf_FontEnumerate(SWF * swf, void (*FontCallback) (void*, U16, U8 *), void*self)
116 if (swf_isFontTag(t)) {
126 if (swf_GetTagID(t) == ST_DEFINEFONT2 || swf_GetTagID(t) == ST_DEFINEFONTINFO || swf_GetTagID(t) == ST_DEFINEFONTINFO2) {
129 swf_GetBlock(t, s, l);
133 (FontCallback) (self, id, s);
141 int swf_FontExtract_DefineFont(int id, SWFFONT * f, TAG * t)
147 if ((!id) || (id == fid)) {
158 f->glyph = (SWFGLYPH*)rfx_calloc(sizeof(SWFGLYPH) * n);
160 for (i = 1; i < n; i++)
162 for (i = 0; i < n; i++)
163 swf_GetSimpleShape(t, &f->glyph[i].shape);
168 int swf_FontExtract_DefineFontInfo(int id, SWFFONT * f, TAG * t)
180 if (f->version > 1) {
181 /* Especially with Flash MX, DefineFont2 may have FontInfo fields,
182 too. However, they only add little information to what's already
183 inside the DefineFont2 tag */
190 f->name = (U8 *) rfx_alloc(l + 1);
191 swf_GetBlock(t, f->name, l);
194 flags = swf_GetU8(t);
196 f->style |= FONT_STYLE_BOLD;
198 f->style |= FONT_STYLE_ITALIC;
200 f->encoding |= FONT_ENCODING_ANSI;
202 f->encoding |= FONT_ENCODING_SHIFTJIS;
204 f->encoding |= FONT_ENCODING_UNICODE;
206 if (t->id == ST_DEFINEFONTINFO2) {
207 f->language = swf_GetU8(t);
210 f->glyph2ascii = (U16 *) rfx_alloc(sizeof(U16) * f->numchars);
212 for (i = 0; i < f->numchars; i++) {
213 f->glyph2ascii[i] = ((flags & FF_WIDECODES) ? swf_GetU16(t) : swf_GetU8(t));
214 if (f->glyph2ascii[i] > maxcode)
215 maxcode = f->glyph2ascii[i];
220 f->maxascii = maxcode;
221 f->ascii2glyph = (int *) rfx_alloc(sizeof(int) * maxcode);
222 memset(f->ascii2glyph, -1, sizeof(int) * maxcode);
224 for (i = 0; i < f->numchars; i++)
225 f->ascii2glyph[f->glyph2ascii[i]] = i;
230 int swf_FontExtract_GlyphNames(int id, SWFFONT * f, TAG * tag)
233 swf_SetTagPos(tag, 0);
235 fid = swf_GetU16(tag);
238 int num = swf_GetU16(tag);
240 f->glyphnames = (char**)rfx_alloc(sizeof(char *) * num);
241 for (t = 0; t < num; t++) {
242 f->glyphnames[t] = strdup(swf_GetString(tag));
249 int swf_FontExtract_DefineFont2(int id, SWFFONT * font, TAG * tag)
256 U8 flags1, langcode, namelen;
257 swf_SetTagPos(tag, 0);
259 fid = swf_GetU16(tag);
263 flags1 = swf_GetU8(tag);
264 langcode = swf_GetU8(tag); //reserved flags
267 font->style |= FONT_STYLE_BOLD;
269 font->style |= FONT_STYLE_ITALIC;
271 font->encoding |= FONT_ENCODING_ANSI;
273 font->encoding |= FONT_ENCODING_UNICODE;
275 font->encoding |= FONT_ENCODING_SHIFTJIS;
277 namelen = swf_GetU8(tag);
278 font->name = (U8 *) rfx_alloc(namelen + 1);
279 font->name[namelen] = 0;
280 swf_GetBlock(tag, font->name, namelen);
282 glyphcount = swf_GetU16(tag);
283 font->numchars = glyphcount;
285 font->glyph = (SWFGLYPH *) rfx_calloc(sizeof(SWFGLYPH) * glyphcount);
286 font->glyph2ascii = (U16 *) rfx_calloc(sizeof(U16) * glyphcount);
288 offset = (U32*)rfx_calloc(sizeof(U32)*(glyphcount+1));
289 offset_start = tag->pos;
291 if (flags1 & 8) { // wide offsets
292 for (t = 0; t < glyphcount; t++)
293 offset[t] = swf_GetU32(tag); //offset[t]
295 if (glyphcount) /* this _if_ is not in the specs */
296 offset[glyphcount] = swf_GetU32(tag); // fontcodeoffset
298 offset[glyphcount] = tag->pos;
300 for (t = 0; t < glyphcount; t++)
301 offset[t] = swf_GetU16(tag); //offset[t]
303 if (glyphcount) /* this _if_ is not in the specs */
304 offset[glyphcount] = swf_GetU16(tag); // fontcodeoffset
306 offset[glyphcount] = tag->pos;
308 for (t = 0; t < glyphcount; t++) {
309 swf_SetTagPos(tag, offset[t]+offset_start);
310 swf_GetSimpleShape(tag, &(font->glyph[t].shape));
314 swf_SetTagPos(tag, offset[glyphcount]+offset_start);
319 for (t = 0; t < glyphcount; t++) {
321 if (flags1 & 4) // wide codes (always on for definefont3)
322 code = swf_GetU16(tag);
324 code = swf_GetU8(tag);
325 font->glyph2ascii[t] = code;
332 font->maxascii = maxcode;
333 font->ascii2glyph = (int *) rfx_alloc(sizeof(int) * maxcode);
334 memset(font->ascii2glyph, -1, sizeof(int) * maxcode);
335 for (t = 0; t < glyphcount; t++) {
336 font->ascii2glyph[font->glyph2ascii[t]] = t;
339 if (flags1 & 128) { // has layout
341 font->layout = (SWFLAYOUT *) rfx_alloc(sizeof(SWFLAYOUT));
342 font->layout->ascent = swf_GetU16(tag);
343 font->layout->descent = swf_GetU16(tag);
344 font->layout->leading = swf_GetU16(tag);
345 for (t = 0; t < glyphcount; t++) {
346 S16 advance = swf_GetS16(tag);
347 font->glyph[t].advance = advance;
349 font->layout->bounds = (SRECT*)rfx_alloc(glyphcount * sizeof(SRECT));
350 for (t = 0; t < glyphcount; t++) {
351 swf_ResetReadBits(tag);
352 swf_GetRect(tag, &font->layout->bounds[t]);
355 kerningcount = swf_GetU16(tag);
356 font->layout->kerningcount = kerningcount;
358 font->layout->kerning = (SWFKERNING *) rfx_alloc(sizeof(SWFKERNING) * kerningcount);
360 font->layout->kerning = (SWFKERNING*)rfx_alloc(sizeof(*font->layout->kerning) * kerningcount);
361 for (t = 0; t < kerningcount; t++) {
362 if (flags1 & 4) { // wide codes
363 font->layout->kerning[t].char1 = swf_GetU16(tag);
364 font->layout->kerning[t].char2 = swf_GetU16(tag);
366 font->layout->kerning[t].char1 = swf_GetU8(tag);
367 font->layout->kerning[t].char2 = swf_GetU8(tag);
369 font->layout->kerning[t].adjustment = swf_GetS16(tag);
376 int swf_FontExtract_DefineFontAlignZones(int id, SWFFONT * font, TAG * tag)
379 swf_SetTagPos(tag, 0);
380 fid = swf_GetU16(tag);
383 font->alignzone_flags = swf_GetU8(tag);
384 font->alignzones = rfx_calloc(sizeof(ALIGNZONE)*font->numchars);
386 while(tag->pos < tag->len) {
387 if(i>=font->numchars)
389 int nr = swf_GetU8(tag); // should be 2
391 fprintf(stderr, "rfxswf: Can't parse alignzone tags with %d zones", nr);
394 U16 x = swf_GetU16(tag);
395 U16 y = swf_GetU16(tag);
396 U16 dx = (nr==2)?swf_GetU16(tag):0xffff;
397 U16 dy = (nr==2)?swf_GetU16(tag):0xffff;
398 U8 xy = swf_GetU8(tag);
401 if((!(xy&1) && (x!=0 || (dx!=0 && dx!=0xffff))) ||
402 (!(xy&2) && (y!=0 || (dy!=0 && dy!=0xffff)))) {
403 fprintf(stderr, "Warning: weird combination of alignzone bits and values (%d x:%04x-%04x y:%04x-%04x)\n", xy,
414 font->alignzones[i].x = x;
415 font->alignzones[i].y = y;
416 font->alignzones[i].dx = dx;
417 font->alignzones[i].dy = dy;
425 #define FEDTJ_PRINT 0x01
426 #define FEDTJ_MODIFY 0x02
427 #define FEDTJ_CALLBACK 0x04
430 swf_FontExtract_DefineTextCallback(int id, SWFFONT * f, TAG * t, int jobs,
431 void (*callback) (void *self,
432 int *chars, int *xpos, int nr, int fontid, int fontsize, int xstart, int ystart, RGBA * color), void *self)
443 memset(&color, 0, sizeof(color));
449 swf_GetMatrix(t, &m);
450 gbits = swf_GetU8(t);
451 abits = swf_GetU8(t);
455 flags = swf_GetU8(t);
459 if (flags & TF_TEXTCONTROL) {
460 if (flags & TF_HASFONT)
462 if (flags & TF_HASCOLOR) {
463 color.r = swf_GetU8(t); // rgb
464 color.g = swf_GetU8(t);
465 color.b = swf_GetU8(t);
466 if (swf_GetTagID(t) == ST_DEFINETEXT2)
467 color.a = swf_GetU8(t);
471 if (flags & TF_HASXOFFSET)
473 if (flags & TF_HASYOFFSET)
475 if (flags & TF_HASFONT)
476 fontsize = swf_GetU16(t);
488 for (i = 0; i < num; i++) {
492 glyph = swf_GetBits(t, gbits);
493 adv = swf_GetBits(t, abits);
497 if (jobs & FEDTJ_PRINT) {
498 int code = f->glyph2ascii[glyph];
501 if (jobs & FEDTJ_MODIFY)
502 f->glyph[glyph].advance = adv * 20; //?
507 if ((id == fid) && (jobs & FEDTJ_PRINT))
509 if (jobs & FEDTJ_CALLBACK)
510 callback(self, buf, advance, num, fid, fontsize, x, y, &color);
518 int swf_ParseDefineText(TAG * tag,
519 void (*callback) (void *self, int *chars, int *ypos, int nr, int fontid, int fontsize, int xstart, int ystart, RGBA * color), void *self)
521 return swf_FontExtract_DefineTextCallback(-1, 0, tag, FEDTJ_CALLBACK, callback, self);
524 int swf_FontExtract_DefineText(int id, SWFFONT * f, TAG * t, int jobs)
526 return swf_FontExtract_DefineTextCallback(id, f, t, jobs, 0, 0);
529 int swf_FontExtract(SWF * swf, int id, SWFFONT * *font)
534 if ((!swf) || (!font))
537 f = (SWFFONT *) rfx_calloc(sizeof(SWFFONT));
543 switch (swf_GetTagID(t)) {
545 nid = swf_FontExtract_DefineFont(id, f, t);
550 nid = swf_FontExtract_DefineFont2(id, f, t);
553 case ST_DEFINEFONTALIGNZONES:
554 nid = swf_FontExtract_DefineFontAlignZones(id, f, t);
557 case ST_DEFINEFONTINFO:
558 case ST_DEFINEFONTINFO2:
559 nid = swf_FontExtract_DefineFontInfo(id, f, t);
564 nid = swf_FontExtract_DefineText(id, f, t, f->layout ? 0 : FEDTJ_MODIFY);
568 nid = swf_FontExtract_GlyphNames(id, f, t);
583 int swf_FontSetID(SWFFONT * f, U16 id)
591 void swf_LayoutFree(SWFLAYOUT * l)
595 rfx_free(l->kerning);
605 static void font_freeglyphnames(SWFFONT*f)
610 for (t = 0; t < f->numchars; t++)
612 if (f->glyphnames[t])
614 rfx_free(f->glyphnames[t]);
615 f->glyphnames[t] = 0;
618 rfx_free(f->glyphnames);
622 static void font_freeusage(SWFFONT*f)
626 rfx_free(f->use->chars);f->use->chars = 0;
628 rfx_free(f->use); f->use = 0;
631 static void font_freelayout(SWFFONT*f)
634 swf_LayoutFree(f->layout);
638 static void font_freename(SWFFONT*f)
646 int swf_FontReduce_old(SWFFONT * f)
650 if ((!f) || (!f->use) || f->use->is_reduced)
655 for (i = 0; i < f->numchars; i++) {
656 if (f->glyph[i].shape && f->use->chars[i]) {
657 f->glyph2ascii[j] = f->glyph2ascii[i];
658 f->glyph[j] = f->glyph[i];
659 f->use->chars[i] = j;
662 f->glyph2ascii[i] = 0;
663 if(f->glyph[i].shape) {
664 swf_ShapeFree(f->glyph[i].shape);
665 f->glyph[i].shape = 0;
666 f->glyph[i].advance = 0;
668 f->use->chars[i] = -1;
672 for (i = 0; i < f->maxascii; i++) {
673 if(f->use->chars[f->ascii2glyph[i]]<0) {
674 f->ascii2glyph[i] = -1;
676 f->ascii2glyph[i] = f->use->chars[f->ascii2glyph[i]];
680 f->maxascii = max_unicode;
681 f->use->is_reduced = 1;
684 font_freeglyphnames(f);
689 int swf_FontReduce_swfc(SWFFONT * f)
693 if ((!f) || (!f->use) || f->use->is_reduced)
696 font_freeglyphnames(f);
699 for (i = 0; i < f->numchars; i++) {
700 if (f->glyph[i].shape && f->use->chars[i]) {
701 f->glyph2ascii[j] = f->glyph2ascii[i];
703 f->layout->bounds[j] = f->layout->bounds[i];
704 f->glyph[j] = f->glyph[i];
705 f->use->chars[i] = j;
708 f->glyph2ascii[i] = 0;
709 if(f->glyph[i].shape) {
710 swf_ShapeFree(f->glyph[i].shape);
711 f->glyph[i].shape = 0;
712 f->glyph[i].advance = 0;
714 f->use->chars[i] = -1;
717 f->use->used_glyphs = j;
718 for (i = 0; i < f->maxascii; i++) {
719 if(f->ascii2glyph[i] > -1) {
720 if (f->use->chars[f->ascii2glyph[i]]<0) {
721 f->use->chars[f->ascii2glyph[i]] = 0;
722 f->ascii2glyph[i] = -1;
724 f->ascii2glyph[i] = f->use->chars[f->ascii2glyph[i]];
725 f->use->chars[f->ascii2glyph[i]] = 1;
730 f->maxascii = max_unicode;
731 f->use->is_reduced = 1;
737 int swf_FontReduce(SWFFONT * f)
742 if ((!f) || (!f->use) || f->use->is_reduced)
746 font_freeglyphnames(f);
748 f->use->used_glyphs= 0;
749 for (i = 0; i < f->numchars; i++) {
750 if(!f->use->chars[i]) {
752 f->glyph2ascii[i] = 0;
754 if(f->glyph[i].shape) {
755 swf_ShapeFree(f->glyph[i].shape);
756 f->glyph[i].shape = 0;
757 f->glyph[i].advance = 0;
759 // f->use->used_glyphs++;
761 f->use->used_glyphs++;
765 for (i = 0; i < f->maxascii; i++) {
766 if(f->ascii2glyph[i] > -1 && !f->use->chars[f->ascii2glyph[i]]) {
768 f->ascii2glyph[i] = -1;
774 f->maxascii = max_unicode;
775 f->numchars = max_glyph;
780 void swf_FontSort(SWFFONT * font)
788 newplace = (int*)rfx_alloc(sizeof(int) * font->numchars);
790 for (i = 0; i < font->numchars; i++) {
793 for (i = 0; i < font->numchars; i++)
794 for (j = 0; j < i; j++) {
795 if (font->glyph2ascii[i] < font->glyph2ascii[j]) {
804 n1 = font->glyph2ascii[i];
805 n2 = font->glyph2ascii[j];
806 font->glyph2ascii[j] = n1;
807 font->glyph2ascii[i] = n2;
812 if (font->glyphnames) {
813 c1 = font->glyphnames[i];
814 c2 = font->glyphnames[j];
815 font->glyphnames[j] = c1;
816 font->glyphnames[i] = c2;
819 r1 = font->layout->bounds[i];
820 r2 = font->layout->bounds[j];
821 font->layout->bounds[j] = r1;
822 font->layout->bounds[i] = r2;
826 newpos = (int*)rfx_alloc(sizeof(int) * font->numchars);
827 for (i = 0; i < font->numchars; i++) {
828 newpos[newplace[i]] = i;
830 for (i = 0; i < font->maxascii; i++) {
831 if (font->ascii2glyph[i] >= 0)
832 font->ascii2glyph[i] = newpos[font->ascii2glyph[i]];
839 void swf_FontPrepareForEditText(SWFFONT * font)
842 swf_FontCreateLayout(font);
846 int swf_FontInitUsage(SWFFONT * f)
851 fprintf(stderr, "Usage initialized twice");
854 f->use = (FONTUSAGE*)rfx_alloc(sizeof(FONTUSAGE));
855 f->use->is_reduced = 0;
856 f->use->used_glyphs = 0;
857 f->use->chars = (int*)rfx_calloc(sizeof(f->use->chars[0]) * f->numchars);
858 f->use->glyphs_specified = 0;
862 void swf_FontClearUsage(SWFFONT * f)
866 rfx_free(f->use->chars); f->use->chars = 0;
867 rfx_free(f->use); f->use = 0;
870 int swf_FontUse(SWFFONT * f, U8 * s)
875 if(*s < f->maxascii && f->ascii2glyph[*s]>=0)
876 swf_FontUseGlyph(f, f->ascii2glyph[*s]);
882 int swf_FontUseUTF8(SWFFONT * f, U8 * s)
889 ascii = readUTF8char(&s);
890 if(ascii < f->maxascii && f->ascii2glyph[ascii]>=0)
891 swf_FontUseGlyph(f, f->ascii2glyph[ascii]);
896 int swf_FontUseAll(SWFFONT* f)
901 swf_FontInitUsage(f);
902 for (i = 0; i < f->numchars; i++)
903 f->use->chars[i] = 1;
904 f->use->used_glyphs = f->numchars;
908 int swf_FontUseGlyph(SWFFONT * f, int glyph)
911 swf_FontInitUsage(f);
912 if(glyph < 0 || glyph >= f->numchars)
914 if(!f->use->chars[glyph])
915 f->use->used_glyphs++;
916 f->use->chars[glyph] = 1;
920 int swf_FontSetDefine(TAG * t, SWFFONT * f)
922 U16 *ofs = (U16 *) rfx_alloc(f->numchars * 2);
927 swf_ResetWriteBits(t);
928 swf_SetU16(t, f->id);
932 for (i = 0; i < f->numchars; i++)
933 if (f->glyph[i].shape) {
935 p += swf_SetSimpleShape(NULL, f->glyph[i].shape);
938 for (i = 0; i < j; i++)
939 swf_SetU16(t, ofs[i] + j * 2);
941 fprintf(stderr, "rfxswf: warning: Font is empty\n");
945 for (i = 0; i < f->numchars; i++)
946 if (f->glyph[i].shape)
947 swf_SetSimpleShape(t, f->glyph[i].shape);
949 swf_ResetWriteBits(t);
954 static inline int fontSize(SWFFONT * font)
958 for (t = 0; t < font->numchars; t++) {
960 if(font->glyph[t].shape)
961 l = (font->glyph[t].shape->bitlen + 7) / 8;
966 return size + (font->numchars + 1) * 2;
969 int swf_FontSetDefine2(TAG * tag, SWFFONT * f)
974 swf_SetU16(tag, f->id);
976 if (f->layout) flags |= 128; // haslayout
977 if (f->numchars > 256)
978 flags |= 4; // widecodes
979 if (f->style & FONT_STYLE_BOLD)
981 if (f->style & FONT_STYLE_ITALIC)
982 flags |= 2; // italic
983 if (f->maxascii >= 256)
984 flags |= 4; //wide codecs
985 if (fontSize(f) > 65535)
986 flags |= 8; //wide offsets
987 flags |= 8 | 4; //FIXME: the above check doesn't work
989 if (f->encoding & FONT_ENCODING_ANSI)
991 if (f->encoding & FONT_ENCODING_UNICODE)
992 flags |= 32; // unicode
993 if (f->encoding & FONT_ENCODING_SHIFTJIS)
994 flags |= 64; // shiftjis
996 swf_SetU8(tag, flags);
997 swf_SetU8(tag, 0); //reserved flags
1000 swf_SetU8(tag, strlen((const char*)f->name)+1);
1001 swf_SetBlock(tag, f->name, strlen((const char*)f->name)+1);
1003 /* font name (="") */
1007 /* number of glyphs */
1008 swf_SetU16(tag, f->numchars);
1009 /* font offset table */
1011 for (t = 0; t <= f->numchars; t++) {
1013 swf_SetU32(tag, /* fontoffset */ 0); /*placeholder */
1015 swf_SetU16(tag, /* fontoffset */ 0); /*placeholder */
1018 for (t = 0; t <= f->numchars; t++) {
1020 tag->data[pos + t * 4] = (tag->len - pos);
1021 tag->data[pos + t * 4 + 1] = (tag->len - pos) >> 8;
1022 tag->data[pos + t * 4 + 2] = (tag->len - pos) >> 16;
1023 tag->data[pos + t * 4 + 3] = (tag->len - pos) >> 24;
1025 if (tag->len - pos > 65535) {
1026 fprintf(stderr, "Internal error: Font too big and WideOffsets flag not set\n");
1029 tag->data[pos + t * 2] = (tag->len - pos);
1030 tag->data[pos + t * 2 + 1] = (tag->len - pos) >> 8;
1032 if (t < f->numchars) {
1033 if(f->glyph[t].shape) {
1034 swf_SetSimpleShape(tag, f->glyph[t].shape);
1036 swf_SetU8(tag, 0); //non-edge(1) + edge flags(5)
1042 /* font code table */
1043 for (t = 0; t < f->numchars; t++) {
1044 if (flags & 4) { /* wide codes */
1045 if(f->glyph2ascii[t]) {
1046 swf_SetU16(tag, f->glyph2ascii[t]);
1051 if(f->glyph2ascii[t]) {
1052 swf_SetU8(tag, f->glyph2ascii[t]);
1060 swf_SetU16(tag, f->layout->ascent);
1061 swf_SetU16(tag, f->layout->descent);
1062 swf_SetU16(tag, f->layout->leading);
1063 for (t = 0; t < f->numchars; t++)
1064 swf_SetU16(tag, f->glyph[t].advance);
1065 for (t = 0; t < f->numchars; t++) {
1066 swf_ResetWriteBits(tag);
1067 swf_SetRect(tag, &f->layout->bounds[t]);
1069 swf_SetU16(tag, f->layout->kerningcount);
1070 for (t = 0; t < f->layout->kerningcount; t++) {
1071 if (flags & 4) { /* wide codes */
1072 swf_SetU16(tag, f->layout->kerning[t].char1);
1073 swf_SetU16(tag, f->layout->kerning[t].char2);
1075 swf_SetU8(tag, f->layout->kerning[t].char1);
1076 swf_SetU8(tag, f->layout->kerning[t].char2);
1078 swf_SetU16(tag, f->layout->kerning[t].adjustment);
1084 void swf_FontAddLayout(SWFFONT * f, int ascent, int descent, int leading)
1086 f->layout = (SWFLAYOUT *) rfx_alloc(sizeof(SWFLAYOUT));
1087 f->layout->ascent = ascent;
1088 f->layout->descent = descent;
1089 f->layout->leading = leading;
1090 f->layout->kerningcount = 0;
1091 f->layout->kerning = 0;
1092 f->layout->bounds = (SRECT *) rfx_calloc(sizeof(SRECT) * f->numchars);
1095 int swf_FontSetInfo(TAG * t, SWFFONT * f)
1102 swf_ResetWriteBits(t);
1103 swf_SetU16(t, f->id);
1104 l = f->name ? strlen((const char *)f->name) : 0;
1109 swf_SetBlock(t, f->name, l);
1110 if (f->numchars >= 256)
1113 if (f->style & FONT_STYLE_BOLD)
1115 if (f->style & FONT_STYLE_ITALIC)
1117 if (f->style & FONT_ENCODING_ANSI)
1119 if (f->style & FONT_ENCODING_SHIFTJIS)
1121 if (f->style & FONT_ENCODING_UNICODE)
1124 swf_SetU8(t, (flags & 0xfe) | wide);
1126 for (i = 0; i < f->numchars; i++) {
1127 if (f->glyph[i].shape) {
1128 int g2a = f->glyph2ascii?f->glyph2ascii[i]:0;
1129 wide ? swf_SetU16(t, g2a) : swf_SetU8(t, g2a);
1136 int swf_TextPrintDefineText(TAG * t, SWFFONT * f)
1138 int id = swf_GetTagID(t);
1139 if ((id == ST_DEFINETEXT) || (id == ST_DEFINETEXT2))
1140 swf_FontExtract_DefineText(f->id, f, t, FEDTJ_PRINT);
1146 void swf_FontFree(SWFFONT * f)
1154 for (i = 0; i < f->numchars; i++)
1155 if (f->glyph[i].shape)
1157 swf_ShapeFree(f->glyph[i].shape);
1158 f->glyph[i].shape = NULL;
1165 rfx_free(f->ascii2glyph);
1166 f->ascii2glyph = NULL;
1170 rfx_free(f->glyph2ascii);
1171 f->glyph2ascii = NULL;
1175 font_freeglyphnames(f);
1181 int swf_TextSetInfoRecord(TAG * t, SWFFONT * font, U16 size, RGBA * color, int x, int y)
1187 flags = TF_TEXTCONTROL | (font ? TF_HASFONT : 0) | (color ? TF_HASCOLOR : 0) | (x ? TF_HASXOFFSET : 0)
1188 | (y ? TF_HASYOFFSET : 0);
1190 swf_SetU8(t, flags);
1192 swf_SetU16(t, font->id);
1194 if (swf_GetTagID(t) == ST_DEFINETEXT2)
1195 swf_SetRGBA(t, color);
1197 swf_SetRGB(t, color);
1200 if(x != SET_TO_ZERO) {
1201 if(x>32767 || x<-32768)
1202 fprintf(stderr, "Warning: Horizontal char position overflow: %d\n", x);
1209 if(y != SET_TO_ZERO) {
1210 if(y>32767 || y<-32768)
1211 fprintf(stderr, "Warning: Vertical char position overflow: %d\n", y);
1218 swf_SetU16(t, size);
1223 static int swf_TextCountBits2(SWFFONT * font, U8 * s, int scale, U8 * gbits, U8 * abits, char *encoding)
1227 if ((!s) || (!font) || ((!gbits) && (!abits)) || (!font->ascii2glyph))
1231 if (!strcmp(encoding, "UTF8"))
1233 else if (!strcmp(encoding, "iso-8859-1"))
1236 fprintf(stderr, "Unknown encoding: %s", encoding);
1244 c = readUTF8char(&s);
1246 if (c < font->maxascii)
1247 glyph = font->ascii2glyph[c];
1249 g = swf_CountUBits(glyph, g);
1250 a = swf_CountBits(((((U32) font->glyph[glyph].advance) * scale) / 20) / 100, a);
1261 static int swf_TextSetCharRecord2(TAG * t, SWFFONT * font, U8 * s, int scale, U8 gbits, U8 abits, char *encoding)
1266 if ((!t) || (!font) || (!s) || (!font->ascii2glyph))
1269 if (!strcmp(encoding, "UTF8"))
1271 else if (!strcmp(encoding, "iso-8859-1"))
1274 fprintf(stderr, "Unknown encoding: %s", encoding);
1277 swf_SetU8(t, l); //placeholder
1285 c = readUTF8char(&s);
1287 if (c < font->maxascii)
1288 g = font->ascii2glyph[c];
1290 swf_SetBits(t, g, gbits);
1291 swf_SetBits(t, ((((U32) font->glyph[g].advance) * scale) / 20) / 100, abits);
1293 /* We split into 127 characters per text field.
1294 We could do 255, by the (formerly wrong) flash specification,
1295 but some SWF parsing code out there still assumes that char blocks
1296 are at max 127 characters, and it would save only a few bits.
1303 PUT8(&t->data[pos], l);
1305 swf_ResetWriteBits(t);
1309 int swf_TextCountBits(SWFFONT * font, U8 * s, int scale, U8 * gbits, U8 * abits)
1311 return swf_TextCountBits2(font, s, scale, gbits, abits, "iso-8859-1");
1314 int swf_TextSetCharRecord(TAG * t, SWFFONT * font, U8 * s, int scale, U8 gbits, U8 abits)
1316 return swf_TextSetCharRecord2(t, font, s, scale, gbits, abits, "iso-8859-1");
1319 int swf_TextCountBitsUTF8(SWFFONT * font, U8 * s, int scale, U8 * gbits, U8 * abits)
1321 return swf_TextCountBits2(font, s, scale, gbits, abits, "UTF8");
1324 int swf_TextSetCharRecordUTF8(TAG * t, SWFFONT * font, U8 * s, int scale, U8 gbits, U8 abits)
1326 return swf_TextSetCharRecord2(t, font, s, scale, gbits, abits, "UTF8");
1329 U32 swf_TextGetWidth(SWFFONT * font, U8 * s, int scale)
1336 if (*s < font->maxascii)
1337 g = font->ascii2glyph[*s];
1339 res += font->glyph[g].advance / 20;
1343 res = (res * scale) / 100;
1348 SRECT swf_TextCalculateBBoxUTF8(SWFFONT * font, U8 * s, int scale)
1355 int c = readUTF8char(&s);
1356 if(c==13 || c==10) {
1361 ypos+=font->layout->leading;
1364 if (c < font->maxascii) {
1365 int g = font->ascii2glyph[c];
1367 SRECT rn = font->layout->bounds[g];
1368 rn.xmin = (rn.xmin * scale) / 20 / 100 + xpos;
1369 rn.xmax = (rn.xmax * scale) / 20 / 100 + xpos;
1370 rn.ymin = (rn.ymin * scale) / 20 / 100 + ypos;
1371 rn.ymax = (rn.ymax * scale) / 20 / 100 + ypos;
1372 swf_ExpandRect2(&r, &rn);
1373 xpos += (font->glyph[g].advance * scale) / 20 / 100;
1381 SWFFONT *swf_ReadFont(const char *filename)
1387 f = open(filename, O_RDONLY|O_BINARY);
1389 if (f < 0 || swf_ReadSWF(f, &swf) < 0) {
1390 fprintf(stderr, "%s is not a valid SWF font file or contains errors.\n", filename);
1396 if (swf_FontExtract(&swf, WRITEFONTID, &font) < 0)
1403 void swf_SetEditText(TAG * tag, U16 flags, SRECT r, const char *text, RGBA * color, int maxlength, U16 font, U16 height, EditTextLayout * layout, const char *variable)
1405 swf_SetRect(tag, &r);
1406 swf_ResetWriteBits(tag);
1408 flags &= ~(ET_HASTEXT | ET_HASTEXTCOLOR | ET_HASMAXLENGTH | ET_HASFONT | ET_HASLAYOUT);
1410 flags |= ET_HASTEXT;
1412 flags |= ET_HASTEXTCOLOR;
1414 flags |= ET_HASMAXLENGTH;
1416 flags |= ET_HASFONT;
1418 flags |= ET_HASLAYOUT;
1420 swf_SetBits(tag, flags, 16);
1422 if (flags & ET_HASFONT) {
1423 swf_SetU16(tag, font); //font
1424 swf_SetU16(tag, height); //fontheight
1426 if (flags & ET_HASTEXTCOLOR) {
1427 swf_SetRGBA(tag, color);
1429 if (flags & ET_HASMAXLENGTH) {
1430 swf_SetU16(tag, maxlength); //maxlength
1432 if (flags & ET_HASLAYOUT) {
1433 swf_SetU8(tag, layout->align); //align
1434 swf_SetU16(tag, layout->leftmargin); //left margin
1435 swf_SetU16(tag, layout->rightmargin); //right margin
1436 swf_SetU16(tag, layout->indent); //indent
1437 swf_SetU16(tag, layout->leading); //leading
1439 swf_SetString(tag, variable);
1440 if (flags & ET_HASTEXT)
1441 swf_SetString(tag, text);
1444 SRECT swf_SetDefineText(TAG * tag, SWFFONT * font, RGBA * rgb, const char *text, int scale)
1448 U8 *utext = (U8 *) strdup(text);
1454 r = swf_TextCalculateBBoxUTF8(font, (U8*)text, scale * 20);
1455 ystep = font->layout->leading;
1457 fprintf(stderr, "No layout information- can't compute text bbox accurately");
1458 /* Hm, without layout information, we can't compute a bounding
1459 box. We could call swf_FontCreateLayout to create a layout,
1460 but the caller probably doesn't want us to mess up his font
1463 r.xmin = r.ymin = 0;
1464 r.xmax = r.ymax = 1024 * 20;
1468 swf_SetRect(tag, &r);
1470 /* The text matrix is pretty boring, as it doesn't apply to
1471 individual characters, but rather whole text objects (or
1472 at least whole char records- haven't tested).
1473 So it can't do anything which we can't already do with
1474 the placeobject tag we use for placing the text on the scene.
1476 swf_SetMatrix(tag, 0);
1478 swf_TextCountBitsUTF8(font, (U8*)text, scale * 20, &gbits, &abits);
1479 swf_SetU8(tag, gbits);
1480 swf_SetU8(tag, abits);
1486 swf_TextSetInfoRecord(tag, font, (scale * 1024) / 100, rgb, x, y); //scale
1489 while(*next && *next!=13 && *next!=10 && count<127) {
1490 readUTF8char(&next);
1493 if(next[0] == 13 || next[0] == 10) {
1498 if(next[0] == 13 && next[1] == 10)
1501 if(next[0] == 13 || next[0] == 10) {
1506 /* now set the text params- notice that a font size of
1507 1024 (or 1024*20 for definefont3) means that the glyphs will
1508 be displayed exactly as they would be in/with a defineshape.
1509 This is not documented in the specs.
1512 /* set the actual text- notice that we just pass our scale
1513 parameter over, as TextSetCharRecord calculates with
1515 swf_TextSetCharRecordUTF8(tag, font, upos, scale * 20, gbits, abits);
1525 void swf_FontCreateLayout(SWFFONT * f)
1534 f->layout = (SWFLAYOUT *) rfx_calloc(sizeof(SWFLAYOUT));
1535 f->layout->bounds = (SRECT *) rfx_alloc(f->numchars * sizeof(SRECT));
1536 f->layout->ascent = 0;
1537 f->layout->descent = 0;
1539 for (t = 0; t < f->numchars; t++) {
1543 shape2 = swf_ShapeToShape2(f->glyph[t].shape);
1545 fprintf(stderr, "Shape parse error\n");
1548 bbox = swf_GetShapeBoundingBox(shape2);
1549 swf_Shape2Free(shape2);
1550 f->layout->bounds[t] = bbox;
1552 width = (bbox.xmax);
1554 /* The following is a heuristic- it may be that extractfont_DefineText
1555 has already found out some widths for individual characters (from the way
1556 they are used)- we now have to guess whether that width might be possible,
1557 which is the case if it isn't either much too big or much too small */
1558 if (width > f->glyph[t].advance * 3 / 2 || width < f->glyph[t].advance / 2)
1559 f->glyph[t].advance = width;
1561 if (-bbox.ymin > f->layout->ascent)
1562 f->layout->ascent = -bbox.ymin;
1563 if (bbox.ymax > f->layout->descent)
1564 f->layout->descent = bbox.ymax;
1568 void swf_DrawText(drawer_t * draw, SWFFONT * font, int size, const char *text)
1570 U8 *s = (U8 *) text;
1576 U32 c = readUTF8char(&s);
1577 int g = font->ascii2glyph[c];
1578 shape = font->glyph[g].shape;
1579 if (((int) g) < 0) {
1580 fprintf(stderr, "No char %d in font %s\n", c, font->name ? (char *) font->name : "?");
1583 shape2 = swf_ShapeToShape2(shape);
1586 if (l->type == moveTo) {
1588 to.x = l->x * size / 100.0 / 20.0 + advance;
1589 to.y = l->y * size / 100.0 / 20.0;
1590 draw->moveTo(draw, &to);
1591 } else if (l->type == lineTo) {
1593 to.x = l->x * size / 100.0 / 20.0 + advance;
1594 to.y = l->y * size / 100.0 / 20.0;
1595 draw->lineTo(draw, &to);
1596 } else if (l->type == splineTo) {
1598 mid.x = l->sx * size / 100.0 / 20.0 + advance;
1599 mid.y = l->sy * size / 100.0 / 20.0;
1600 to.x = l->x * size / 100.0 / 20.0 + advance;
1601 to.y = l->y * size / 100.0 / 20.0;
1602 draw->splineTo(draw, &mid, &to);
1606 swf_Shape2Free(shape2);
1607 advance += font->glyph[g].advance * size / 100.0 / 20.0;
1611 void swf_WriteFont_AS3(SWFFONT * font, char *filename)
1614 swf_FontCreateLayout(font);
1617 memset(&swf, 0, sizeof(SWF));
1618 swf.fileVersion = 9;
1619 swf.frameRate = 0x4000;
1620 swf.movieSize.xmax = 200;
1621 swf.movieSize.ymax = 200;
1623 if(!font->id) font->id=1;
1626 swf.firstTag = tag = swf_InsertTag(tag, ST_DEFINEFONT3);
1627 swf_FontSetDefine2(tag, font);
1629 char*name = font->name?(char*)font->name:"font";
1631 tag = swf_InsertTag(tag, ST_NAMECHARACTER);
1632 swf_SetU16(tag, font->id);
1633 swf_SetString(tag, name);
1634 tag = swf_InsertTag(tag, ST_EXPORTASSETS);
1636 swf_SetU16(tag, font->id);
1637 swf_SetString(tag, name);
1638 tag = swf_AddAS3FontDefine(tag, font->id, (char*)font->name);
1640 tag = swf_InsertTag(tag, ST_END);
1641 swf_SaveSWF(&swf, filename);
1645 void swf_WriteFont(SWFFONT * font, char *filename)
1648 swf_FontCreateLayout(font);
1657 memset(&swf, 0, sizeof(SWF));
1658 swf.fileVersion = 8;
1659 swf.frameRate = 0x4000;
1660 swf.movieSize.xmax = 1024*20;
1661 swf.movieSize.ymax = 768*20;
1664 swf.firstTag = tag = swf_InsertTag(NULL, ST_SETBACKGROUNDCOLOR);
1665 swf_SetU8(tag, 0xe0);swf_SetU8(tag, 0xe0);swf_SetU8(tag, 0xff);
1667 tag = swf_InsertTag(tag, ST_DEFINEFONT3);
1668 swf_FontSetDefine2(tag, font);
1670 if(font->glyphnames) {
1672 tag = swf_InsertTag(tag, ST_GLYPHNAMES);
1673 swf_SetU16(tag, font->id);
1674 swf_SetU16(tag, font->numchars);
1675 for (c = 0; c < font->numchars; c++) {
1676 if (font->glyphnames[c])
1677 swf_SetString(tag, font->glyphnames[c]);
1679 swf_SetString(tag, "");
1685 RGBA white = {255,255,255,255};
1686 RGBA black = {255,0,0,0};
1687 RGBA gray50 = {255,128,128,128};
1688 RGBA green = {255,0,255,0};
1690 SCOORD miny = SCOORD_MAX;
1691 SCOORD maxy = SCOORD_MIN;
1693 U16 max_advance = 0;
1694 char*flags = rfx_calloc(font->numchars);
1695 double*xmin = rfx_calloc(sizeof(double)*(font->numchars+1));
1696 double*xmax = rfx_calloc(sizeof(double)*(font->numchars+1));
1697 int*xpos = rfx_calloc(sizeof(int)*(font->numchars+1));
1698 for(t=0;t<font->numchars;t++) {
1699 SHAPE*s = font->glyph[t].shape;
1700 SHAPE2*s2 = swf_ShapeToShape2(s);
1701 SRECT r = swf_GetShapeBoundingBox(s2);
1703 // inside a definefont3, everything is 20x the resolution:
1704 double rx1 = r.xmin / 20.0;
1705 double ry1 = r.ymin / 20.0;
1706 double rx2 = r.xmax / 20.0;
1707 double ry2 = r.ymax / 20.0;
1712 if(ry1<miny) {miny=ry1;}
1713 if(ry2>maxy) {maxy=ry2;}
1714 swf_Shape2Free(s2);free(s2);
1715 width += font->glyph[t].advance;
1716 if(font->glyph[t].advance>max_advance)
1717 max_advance = font->glyph[t].advance;
1720 if(miny==SCOORD_MAX) miny=maxy=0;
1721 if(miny==maxy) maxy=miny+1;
1723 /* scale the font so that it's 256 pixels high */
1724 double scale = (int)((256.0*1024.0/(maxy-miny))*20.0);
1725 double overlarge_factor;
1729 overlarge_factor = scale / 32767.0;
1732 overlarge_factor = 1.0;
1736 int spriteid = id++;
1739 r.ymin = miny*fontsize/1024;
1740 r.xmax = width*fontsize/20480;
1741 r.ymax = maxy*fontsize/1024;
1742 tag = swf_InsertTag(tag, ST_DEFINETEXT);
1743 swf_SetU16(tag, textid);
1744 swf_SetRect(tag, &r);
1745 swf_SetMatrix(tag, NULL);
1748 U8 gbits = swf_CountBits(font->numchars, 0);
1749 swf_SetU8(tag, gbits);
1750 swf_SetU8(tag, abits);
1752 RGBA rgb = {255,0,0,0};
1754 swf_TextSetInfoRecord(tag, font, fontsize, &rgb, SET_TO_ZERO, SET_TO_ZERO);
1755 ActionTAG*array = 0;
1757 array = action_PushString(array, "xpos");
1758 for(t=0;t<font->numchars;t++) {
1760 int width = abs((xmax[t] - xmin[t+1])*fontsize/1024) + 60;
1761 array = action_PushInt(array, x/20 +(xmin[t]*scale/1024)/20);
1762 x += width * overlarge_factor;
1763 swf_SetBits(tag, t, gbits);
1764 swf_SetBits(tag, width, abits);
1765 swf_SetU8(tag, 128);
1767 array = action_PushInt(array, x/20);
1768 array = action_PushInt(array, font->numchars+1);
1769 array = action_InitArray(array);
1770 array = action_SetVariable(array);
1774 tag = swf_InsertTag(tag, ST_DEFINESHAPE2);
1777 int ls = swf_ShapeAddLineStyle(s,20,&white);
1779 swf_SetU16(tag,shapeid);
1785 swf_SetRect(tag,&r);
1786 swf_SetShapeHeader(tag,s);
1787 swf_ShapeSetAll(tag,s,0,0,ls,0,0);
1789 /* Ç and  are good chars to test ascent/descent extend */
1790 int y1 = (-font->layout->ascent-miny*20.0)*256.0/(maxy-miny);
1791 int y2 = (font->layout->descent-miny*20.0)*256.0/(maxy-miny);
1793 swf_ShapeSetMove(tag,s,0,y1);
1794 swf_ShapeSetLine(tag,s,width,0);
1795 swf_ShapeSetMove(tag,s,0,y2);
1796 swf_ShapeSetLine(tag,s,width,0);
1798 swf_ShapeSetEnd(tag);
1800 tag = swf_InsertTag(tag, ST_PLACEOBJECT2);
1801 swf_ObjectPlace(tag, shapeid, depth++, NULL, NULL, NULL);
1806 for(t=0;t<font->numchars;t++) {
1807 tag = swf_InsertTag(tag, ST_DEFINESHAPE2);
1810 int ls = swf_ShapeAddLineStyle(s,20*2,&black);
1811 int ls2 = swf_ShapeAddLineStyle(s,20*2,&green);
1812 int fs = swf_ShapeAddSolidFillStyle(s, &gray50);
1814 swf_SetU16(tag,shapeid);
1820 swf_SetRect(tag,&r);
1821 swf_SetShapeHeader(tag,s);
1822 swf_ShapeSetAll(tag,s,0,0,ls,fs,0);
1823 SHAPE2*s2 = swf_ShapeToShape2(font->glyph[t].shape);
1824 SHAPELINE*l = s2->lines;
1825 int lastx=0,lasty=0;
1827 double x1 = (1024*20 - (xmax[t] - xmin[t])*20*2*scale/20480.0)/2;
1828 double y1 = -miny*20*scale*2/20480.0;
1829 double scalex = scale*2/20480.0;
1830 double scaley = scale*2/20480.0;
1833 int lx = (l->x)*scalex+x1;
1834 int ly = (l->y)*scaley+y1;
1835 int sx = (l->sx)*scalex+x1;
1836 int sy = (l->sy)*scaley+y1;
1837 if(l->type == moveTo) {
1838 swf_ShapeSetMove(tag,s,lx,ly);
1839 } else if(l->type == lineTo) {
1840 swf_ShapeSetLine(tag,s,lx-lastx,ly-lasty);
1841 } else if(l->type == splineTo) {
1842 swf_ShapeSetCurve(tag,s,sx-lastx,sy-lasty,lx-sx,ly-sy);
1849 if(font->alignzones) {
1850 ALIGNZONE*zone = &font->alignzones[t];
1851 swf_ShapeSetAll(tag,s,0,0,ls2,SET_TO_ZERO,SET_TO_ZERO);
1852 if((zone->x&zone->dx)!=0xffff) {
1853 double x = F16toFloat(zone->x)*20480.0*scalex+x1;
1854 double dx = (F16toFloat(zone->x)+F16toFloat(zone->dx))*20480.0*scalex+x1;
1855 swf_ShapeSetMove(tag,s,x,0);
1856 swf_ShapeSetLine(tag,s,0,1024*20);
1857 swf_ShapeSetMove(tag,s,dx,0);
1858 swf_ShapeSetLine(tag,s,0,1024*20);
1860 if((zone->y&zone->dy)!=0xffff) {
1861 double y = -F16toFloat(zone->y)*20480.0*scaley+y1;
1862 double dy = -(F16toFloat(zone->y)+F16toFloat(zone->dy))*20480.0*scaley+y1;
1863 swf_ShapeSetMove(tag,s,0,y);
1864 swf_ShapeSetLine(tag,s,1024*20,0);
1865 swf_ShapeSetMove(tag,s,0,dy);
1866 swf_ShapeSetLine(tag,s,1024*20,0);
1870 swf_ShapeSetEnd(tag);
1873 tag = swf_InsertTag(tag, ST_DEFINESPRITE);
1875 swf_SetU16(tag, spriteid);
1877 tag = swf_InsertTag(tag, ST_PLACEOBJECT2);
1878 swf_ObjectPlace(tag, shapeid, 1, NULL, NULL, NULL);
1879 tag = swf_InsertTag(tag, ST_END);
1880 tag = swf_InsertTag(tag, ST_PLACEOBJECT2);
1882 swf_GetMatrix(0, &m);
1885 sprintf(txt, "char%d", font->numchars-t);
1886 swf_ObjectPlace(tag, spriteid, depth++, &m, NULL, txt);
1890 tag = swf_InsertTag(tag, ST_DEFINESHAPE2);
1892 RGBA blue = {0xff,0xc0,0xc0,0xff};
1893 swf_ShapeSetRectangle(tag, shapeid, 20, 20, &blue);
1894 tag = swf_InsertTag(tag, ST_DEFINESPRITE);
1896 swf_SetU16(tag, spriteid2);
1898 tag = swf_InsertTag(tag, ST_PLACEOBJECT2);
1899 swf_ObjectPlace(tag, shapeid, 1, NULL, NULL, NULL);
1900 tag = swf_InsertTag(tag, ST_END);
1901 tag = swf_InsertTag(tag, ST_PLACEOBJECT2);
1902 swf_ObjectPlace(tag, spriteid2, depth++, NULL, NULL, "marker");
1905 tag = swf_InsertTag(tag, ST_DEFINESPRITE);
1906 swf_SetU16(tag, spriteid);
1908 tag = swf_InsertTag(tag, ST_PLACEOBJECT2);
1910 swf_GetMatrix(0, &m);
1911 m.sx = 65536 * overlarge_factor;
1912 m.sy = 65536 * overlarge_factor;
1914 m.ty = -miny*256*20/(maxy-miny);
1915 swf_ObjectPlace(tag, textid, 1, &m, NULL, NULL);
1916 tag = swf_InsertTag(tag, ST_END);
1917 tag = swf_InsertTag(tag, ST_PLACEOBJECT2);
1918 swf_ObjectPlace(tag, spriteid, depth++, NULL, NULL, "textbar");
1921 RGBA blue2 = {0x80,0x80,0xff,0x80};
1922 tag = swf_InsertTag(tag, ST_DEFINESHAPE3);
1924 swf_ShapeSetRectangleWithBorder(tag, shapeid2, 20, 20, &blue2, 0, &white);
1925 tag = swf_InsertTag(tag, ST_DEFINESPRITE);
1927 swf_SetU16(tag, spriteid3);
1929 tag = swf_InsertTag(tag, ST_PLACEOBJECT2);
1930 swf_ObjectPlace(tag, shapeid2, 1, NULL, NULL, NULL);
1931 tag = swf_InsertTag(tag, ST_END);
1932 tag = swf_InsertTag(tag, ST_PLACEOBJECT2);
1933 swf_ObjectPlace(tag, spriteid3, depth++, NULL, NULL, "marker2");
1937 " var mouseListener = new Object();"
1940 " var currentMouseOver, currentChar;"
1941 " mouseListener.onMouseDown = function() { "
1942 " eval(\"_root.char\"+currentChar)._y = 20000;"
1943 " currentChar = currentMouseOver;"
1944 " var i = currentMouseOver;"
1945 " eval(\"_root.char\"+i)._y = 256;"
1946 " _root.marker2._yscale=256*100;"
1947 " _root.marker2._xscale=(xpos[i-1]-xpos[i])*100;"
1948 " _root.marker2._x=xpos[i]+myx;"
1950 " mouseListener.onMouseMove = function() { "
1951 " if(_ymouse<256) {"
1952 " speed = Math.abs(_xmouse-512)>256?(512-_xmouse)/8:0;"
1957 " setInterval( function(){ "
1958 " if(_ymouse<256) {"
1959 " var i, x=_xmouse-_root.textbar._x;"
1960 " for(i=xpos.length-1;i>0;i--) {"
1961 " if(x<xpos[i-1]) break;"
1963 " currentMouseOver = i;"
1964 " _root.marker._yscale=256*100;"
1965 " _root.marker._xscale=(xpos[i-1]-xpos[i])*100;"
1966 " _root.marker._x=xpos[i]+myx;"
1967 " _root.textbar._x += 0.05;"
1969 " if(myx+speed>0) {"
1971 " } else if(myx+speed<-xpos[0]+1024) {"
1975 " _root.textbar._x = myx;"
1976 " _root.marker._x += speed;"
1977 " _root.marker2._x += speed;"
1979 " Mouse.addListener(mouseListener);"
1981 ActionTAG* atag = swf_ActionCompile(data, 6);
1983 tag = swf_InsertTag(tag, ST_DOACTION);
1984 swf_ActionSet(tag, array);
1985 swf_ActionSet(tag, atag);
1987 swf_ActionFree(atag);
1989 tag = swf_InsertTag(tag, ST_SHOWFRAME);
1996 tag = swf_InsertTag(tag, ST_END);
1998 swf.compressed = -1;
1999 swf_SaveSWF(&swf, filename);