LCOV - code coverage report
Current view: top level - scene_manager - swf_parse.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 1160 1511 76.8 %
Date: 2021-04-29 23:48:07 Functions: 53 58 91.4 %

          Line data    Source code
       1             : /*
       2             :  *                      GPAC - Multimedia Framework C SDK
       3             :  *
       4             :  *                      Authors: Jean Le Feuvre
       5             :  *                      Copyright (c) Telecom ParisTech 2000-2020
       6             :  *                                      All rights reserved
       7             :  *
       8             :  *  This file is part of GPAC / Scene Management sub-project
       9             :  *
      10             :  *  GPAC is free software; you can redistribute it and/or modify
      11             :  *  it under the terms of the GNU Lesser General Public License as published by
      12             :  *  the Free Software Foundation; either version 2, or (at your option)
      13             :  *  any later version.
      14             :  *
      15             :  *  GPAC is distributed in the hope that it will be useful,
      16             :  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
      17             :  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      18             :  *  GNU Lesser General Public License for more details.
      19             :  *
      20             :  *  You should have received a copy of the GNU Lesser General Public
      21             :  *  License along with this library; see the file COPYING.  If not, write to
      22             :  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
      23             :  *
      24             :  */
      25             : 
      26             : 
      27             : #include <gpac/nodes_mpeg4.h>
      28             : #include <gpac/internal/swf_dev.h>
      29             : #include <gpac/avparse.h>
      30             : 
      31             : #ifndef GPAC_DISABLE_SWF_IMPORT
      32             : 
      33             : 
      34             : #include <zlib.h>
      35             : 
      36             : enum
      37             : {
      38             :         SWF_END = 0,
      39             :         SWF_SHOWFRAME = 1,
      40             :         SWF_DEFINESHAPE = 2,
      41             :         SWF_FREECHARACTER = 3,
      42             :         SWF_PLACEOBJECT = 4,
      43             :         SWF_REMOVEOBJECT = 5,
      44             :         SWF_DEFINEBITS = 6,
      45             :         SWF_DEFINEBITSJPEG = 6,
      46             :         SWF_DEFINEBUTTON = 7,
      47             :         SWF_JPEGTABLES = 8,
      48             :         SWF_SETBACKGROUNDCOLOR = 9,
      49             :         SWF_DEFINEFONT = 10,
      50             :         SWF_DEFINETEXT = 11,
      51             :         SWF_DOACTION = 12,
      52             :         SWF_DEFINEFONTINFO = 13,
      53             :         SWF_DEFINESOUND = 14,
      54             :         SWF_STARTSOUND = 15,
      55             :         SWF_DEFINEBUTTONSOUND = 17,
      56             :         SWF_SOUNDSTREAMHEAD = 18,
      57             :         SWF_SOUNDSTREAMBLOCK = 19,
      58             :         SWF_DEFINEBITSLOSSLESS = 20,
      59             :         SWF_DEFINEBITSJPEG2 = 21,
      60             :         SWF_DEFINESHAPE2 = 22,
      61             :         SWF_DEFINEBUTTONCXFORM = 23,
      62             :         SWF_PROTECT = 24,
      63             :         SWF_PLACEOBJECT2 = 26,
      64             :         SWF_REMOVEOBJECT2 = 28,
      65             :         SWF_DEFINESHAPE3 = 32,
      66             :         SWF_DEFINETEXT2 = 33,
      67             :         SWF_DEFINEBUTTON2 = 34,
      68             :         SWF_DEFINEBITSJPEG3 = 35,
      69             :         SWF_DEFINEBITSLOSSLESS2 = 36,
      70             :         SWF_DEFINEEDITTEXT = 37,
      71             :         SWF_DEFINEMOVIE = 38,
      72             :         SWF_DEFINESPRITE = 39,
      73             :         SWF_NAMECHARACTER = 40,
      74             :         SWF_SERIALNUMBER = 41,
      75             :         SWF_GENERATORTEXT = 42,
      76             :         SWF_FRAMELABEL = 43,
      77             :         SWF_SOUNDSTREAMHEAD2 = 45,
      78             :         SWF_DEFINEMORPHSHAPE = 46,
      79             :         SWF_DEFINEFONT2 = 48,
      80             :         SWF_TEMPLATECOMMAND = 49,
      81             :         SWF_GENERATOR3 = 51,
      82             :         SWF_EXTERNALFONT = 52,
      83             :         SWF_EXPORTASSETS = 56,
      84             :         SWF_IMPORTASSETS        = 57,
      85             :         SWF_ENABLEDEBUGGER = 58,
      86             :         SWF_MX0 = 59,
      87             :         SWF_MX1 = 60,
      88             :         SWF_MX2 = 61,
      89             :         SWF_MX3 = 62,
      90             :         SWF_MX4 = 63,
      91             :         SWF_REFLEX = 777
      92             : };
      93             : 
      94             : 
      95           6 : static void swf_init_decompress(SWFReader *read)
      96             : {
      97             :         u32 size, dst_size;
      98             :         uLongf destLen;
      99             :         char *src, *dst;
     100             : 
     101             :         assert(gf_bs_get_size(read->bs)-8 < (u64)1<<31); /*must fit within 32 bits*/
     102           6 :         size = (u32) gf_bs_get_size(read->bs)-8;
     103           6 :         dst_size = read->length;
     104           6 :         src = gf_malloc(sizeof(char)*size);
     105           6 :         dst = gf_malloc(sizeof(char)*dst_size);
     106             :         memset(dst, 0, sizeof(char)*8);
     107           6 :         gf_bs_read_data(read->bs, src, size);
     108           6 :         dst_size -= 8;
     109           6 :         destLen = (uLongf)dst_size;
     110           6 :         uncompress((Bytef *) dst+8, &destLen, (Bytef *) src, size);
     111             :         dst_size += 8;
     112           6 :         gf_free(src);
     113           6 :         read->mem = dst;
     114           6 :         gf_bs_del(read->bs);
     115           6 :         read->bs = gf_bs_new(read->mem, dst_size, GF_BITSTREAM_READ);
     116           6 :         gf_bs_skip_bytes(read->bs, 8);
     117           6 : }
     118             : 
     119             : 
     120             : static GF_Err swf_seek_file_to(SWFReader *read, u32 size)
     121             : {
     122         407 :         return gf_bs_seek(read->bs, size);
     123             : }
     124             : 
     125             : static u32 swf_get_file_pos(SWFReader *read)
     126             : {
     127       21883 :         return (u32) gf_bs_get_position(read->bs);
     128             : }
     129             : 
     130             : static u32 swf_read_data(SWFReader *read, char *data, u32 data_size)
     131             : {
     132         630 :         return gf_bs_read_data(read->bs, data, data_size);
     133             : }
     134             : 
     135             : static u32 swf_read_int(SWFReader *read, u32 nbBits)
     136             : {
     137     1605118 :         return gf_bs_read_int(read->bs, nbBits);
     138             : }
     139             : 
     140      146637 : static s32 swf_read_sint(SWFReader *read, u32 nbBits)
     141             : {
     142             :         u32 r = 0;
     143             :         u32 i;
     144      146637 :         if (!nbBits)return 0;
     145      292250 :         r = swf_read_int(read, 1) ? 0xFFFFFFFF : 0;
     146     1045924 :         for (i=1; i<nbBits; i++) {
     147     1045924 :                 r <<= 1;
     148     2091848 :                 r |= swf_read_int(read, 1);
     149             :         }
     150      146125 :         return (s32) r;
     151             : }
     152             : 
     153             : static u32 swf_align(SWFReader *read)
     154             : {
     155       31587 :         return gf_bs_align(read->bs);
     156             : }
     157             : 
     158             : static void swf_skip_data(SWFReader *read, u32 size)
     159             : {
     160         196 :         while (size && !read->ioerr) {
     161         182 :                 swf_read_int(read, 8);
     162         182 :                 size --;
     163             :         }
     164             : }
     165             : 
     166        1324 : static void swf_get_rec(SWFReader *read, SWFRec *rc)
     167             : {
     168             :         u32 nbbits;
     169        1324 :         swf_align(read);
     170        1324 :         nbbits = swf_read_int(read, 5);
     171        1324 :         rc->x = FLT2FIX( swf_read_sint(read, nbbits) * SWF_TWIP_SCALE );
     172        1324 :         rc->w = FLT2FIX( swf_read_sint(read, nbbits) * SWF_TWIP_SCALE );
     173        1324 :         rc->w -= rc->x;
     174        1324 :         rc->y = FLT2FIX( swf_read_sint(read, nbbits) * SWF_TWIP_SCALE );
     175        1324 :         rc->h = FLT2FIX( swf_read_sint(read, nbbits) * SWF_TWIP_SCALE );
     176        1324 :         rc->h -= rc->y;
     177        1324 : }
     178             : 
     179        1590 : static u32 swf_get_32(SWFReader *read)
     180             : {
     181             :         u32 val, res;
     182        1590 :         val = swf_read_int(read, 32);
     183             :         res = (val&0xFF);
     184        1590 :         res <<=8;
     185        1590 :         res |= ((val>>8)&0xFF);
     186        1590 :         res<<=8;
     187        1590 :         res |= ((val>>16)&0xFF);
     188        1590 :         res<<=8;
     189        1590 :         res|= ((val>>24)&0xFF);
     190        1590 :         return res;
     191             : }
     192             : 
     193             : static u16 swf_get_16(SWFReader *read)
     194             : {
     195             :         u16 val, res;
     196       45200 :         val = swf_read_int(read, 16);
     197             :         res = (val&0xFF);
     198             :         res <<=8;
     199       22419 :         res |= ((val>>8)&0xFF);
     200             :         return res;
     201             : }
     202             : 
     203         320 : static s16 swf_get_s16(SWFReader *read)
     204             : {
     205             :         s16 val;
     206             :         u8 v1;
     207         640 :         v1 = swf_read_int(read, 8);
     208         320 :         val = swf_read_sint(read, 8);
     209         320 :         val = (val<<8)&0xFF00;
     210         320 :         val |= (v1&0xFF);
     211         320 :         return val;
     212             : }
     213             : 
     214        3006 : static u32 swf_get_color(SWFReader *read)
     215             : {
     216             :         u32 res;
     217             :         res = 0xFF00;
     218        3006 :         res |= swf_read_int(read, 8);
     219        3006 :         res<<=8;
     220        6012 :         res |= swf_read_int(read, 8);
     221        3006 :         res<<=8;
     222        6012 :         res |= swf_read_int(read, 8);
     223        3006 :         return res;
     224             : }
     225             : 
     226          61 : static u32 swf_get_argb(SWFReader *read)
     227             : {
     228             :         u32 res, al;
     229          61 :         res = swf_read_int(read, 8);
     230          61 :         res<<=8;
     231         122 :         res |= swf_read_int(read, 8);
     232          61 :         res<<=8;
     233         122 :         res |= swf_read_int(read, 8);
     234          61 :         al = swf_read_int(read, 8);
     235          61 :         return ((al<<24) | res);
     236             : }
     237             : 
     238        4835 : static u32 swf_get_matrix(SWFReader *read, GF_Matrix2D *mat)
     239             : {
     240             :         u32 bits_read;
     241             :         u32 flag, nb_bits;
     242             : 
     243             :         memset(mat, 0, sizeof(GF_Matrix2D));
     244        4835 :         mat->m[0] = mat->m[4] = FIX_ONE;
     245             : 
     246        4835 :         bits_read = swf_align(read);
     247             : 
     248        4835 :         flag = swf_read_int(read, 1);
     249        4835 :         bits_read += 1;
     250        4835 :         if (flag) {
     251        3714 :                 nb_bits = swf_read_int(read, 5);
     252             : #ifdef GPAC_FIXED_POINT
     253             :                 mat->m[0] = swf_read_sint(read, nb_bits);
     254             :                 mat->m[4] = swf_read_sint(read, nb_bits);
     255             : #else
     256        3714 :                 mat->m[0] = (Float) swf_read_sint(read, nb_bits);
     257        3714 :                 mat->m[0] /= 0x10000;
     258        3714 :                 mat->m[4] = (Float) swf_read_sint(read, nb_bits);
     259        3714 :                 mat->m[4] /= 0x10000;
     260             : #endif
     261        3714 :                 bits_read += 5 + 2*nb_bits;
     262             :         }
     263        4835 :         flag = swf_read_int(read, 1);
     264        4835 :         bits_read += 1;
     265        4835 :         if (flag) {
     266        2061 :                 nb_bits = swf_read_int(read, 5);
     267             :                 /*WATCHOUT FOR ORDER*/
     268             : #ifdef GPAC_FIXED_POINT
     269             :                 mat->m[3] = swf_read_sint(read, nb_bits);
     270             :                 mat->m[1] = swf_read_sint(read, nb_bits);
     271             : #else
     272        2061 :                 mat->m[3] = (Float) swf_read_sint(read, nb_bits);
     273        2061 :                 mat->m[3] /= 0x10000;
     274        2061 :                 mat->m[1] = (Float) swf_read_sint(read, nb_bits);
     275        2061 :                 mat->m[1] /= 0x10000;
     276             : #endif
     277        2061 :                 bits_read += 5 + 2*nb_bits;
     278             :         }
     279        4835 :         nb_bits = swf_read_int(read, 5);
     280        4835 :         bits_read += 5 + 2*nb_bits;
     281        4835 :         if (nb_bits) {
     282        4676 :                 mat->m[2] = FLT2FIX( swf_read_sint(read, nb_bits) * SWF_TWIP_SCALE );
     283        4676 :                 mat->m[5] = FLT2FIX( swf_read_sint(read, nb_bits) * SWF_TWIP_SCALE );
     284             :         }
     285        4835 :         return bits_read;
     286             : }
     287             : 
     288             : #define SWF_COLOR_SCALE                         (1/256.0f)
     289             : 
     290         180 : static void swf_get_colormatrix(SWFReader *read, GF_ColorMatrix *cmat)
     291             : {
     292             :         Bool has_add, has_mul;
     293             :         u32 nbbits;
     294             :         memset(cmat, 0, sizeof(GF_ColorMatrix));
     295         180 :         cmat->m[0] = cmat->m[6] = cmat->m[12] = cmat->m[18] = FIX_ONE;
     296             : 
     297         180 :         has_add = swf_read_int(read, 1);
     298         180 :         has_mul = swf_read_int(read, 1);
     299         180 :         nbbits = swf_read_int(read, 4);
     300         180 :         if (has_mul) {
     301          32 :                 cmat->m[0] = FLT2FIX( swf_read_sint(read, nbbits) * SWF_COLOR_SCALE );
     302          32 :                 cmat->m[6] = FLT2FIX( swf_read_sint(read, nbbits) * SWF_COLOR_SCALE );
     303          32 :                 cmat->m[12] = FLT2FIX( swf_read_sint(read, nbbits) * SWF_COLOR_SCALE );
     304          32 :                 cmat->m[18] = FLT2FIX( swf_read_sint(read, nbbits) * SWF_COLOR_SCALE );
     305             :         }
     306         180 :         if (has_add) {
     307         104 :                 cmat->m[4] = FLT2FIX( swf_read_sint(read, nbbits) * SWF_COLOR_SCALE );
     308         104 :                 cmat->m[9] = FLT2FIX( swf_read_sint(read, nbbits) * SWF_COLOR_SCALE );
     309         104 :                 cmat->m[14] = FLT2FIX( swf_read_sint(read, nbbits) * SWF_COLOR_SCALE );
     310         104 :                 cmat->m[19] = FLT2FIX( swf_read_sint(read, nbbits) * SWF_COLOR_SCALE );
     311             :         }
     312         180 :         cmat->identity = 0;
     313         180 :         if ((cmat->m[0] == cmat->m[6])
     314         180 :                 && (cmat->m[0] == cmat->m[12])
     315         180 :                 && (cmat->m[0] == cmat->m[18])
     316         148 :                 && (cmat->m[0] == FIX_ONE)
     317         148 :                 && (cmat->m[4] == cmat->m[9])
     318         146 :                 && (cmat->m[4] == cmat->m[14])
     319         146 :                 && (cmat->m[4] == cmat->m[19])
     320          48 :                 && (cmat->m[4] == 0))
     321          48 :                 cmat->identity = 1;
     322         180 : }
     323             : 
     324          15 : static char *swf_get_string(SWFReader *read)
     325             : {
     326             :         char szName[1024];
     327             :         char *name;
     328             :         u32 i = 0;
     329             : 
     330          15 :         if (read->size>1024) {
     331           0 :                 name = gf_malloc(sizeof(char)*read->size);
     332             :         } else {
     333             :                 name = szName;
     334             :         }
     335             :         while (1) {
     336         444 :                 name[i] = swf_read_int(read, 8);
     337         153 :                 if (!name[i]) break;
     338         138 :                 i++;
     339             :         }
     340          15 :         if (read->size>1024) {
     341           0 :                 return gf_realloc(name, sizeof(char)*(strlen(name)+1));
     342             :         } else {
     343          15 :                 return gf_strdup(szName);
     344             :         }
     345             : }
     346             : 
     347        3175 : static SWFShapeRec *swf_new_shape_rec()
     348             : {
     349             :         SWFShapeRec *style;
     350        3175 :         GF_SAFEALLOC(style, SWFShapeRec);
     351        3175 :         if (!style) return NULL;
     352        3175 :         GF_SAFEALLOC(style->path, SWFPath);
     353        3175 :         if (!style->path) {
     354           0 :                 gf_free(style);
     355           0 :                 return NULL;
     356             :         }
     357             :         return style;
     358             : }
     359             : 
     360        1515 : static SWFShapeRec *swf_clone_shape_rec(SWFShapeRec *old_sr)
     361             : {
     362        1515 :         SWFShapeRec *new_sr = (SWFShapeRec *)gf_malloc(sizeof(SWFShapeRec));
     363             :         memcpy(new_sr, old_sr, sizeof(SWFShapeRec));
     364        1515 :         new_sr->path = (SWFPath*)gf_malloc(sizeof(SWFPath));
     365             :         memset(new_sr->path, 0, sizeof(SWFPath));
     366             : 
     367        1515 :         if (old_sr->nbGrad) {
     368         206 :                 new_sr->grad_col = (u32*)gf_malloc(sizeof(u32) * old_sr->nbGrad);
     369         206 :                 memcpy(new_sr->grad_col, old_sr->grad_col, sizeof(u32) * old_sr->nbGrad);
     370         206 :                 new_sr->grad_ratio = (u8*)gf_malloc(sizeof(u8) * old_sr->nbGrad);
     371         206 :                 memcpy(new_sr->grad_ratio, old_sr->grad_ratio, sizeof(u8) * old_sr->nbGrad);
     372             :         }
     373        1515 :         return new_sr;
     374             : }
     375             : 
     376             : /*parse/append fill and line styles*/
     377        1427 : static void swf_parse_styles(SWFReader *read, u32 revision, SWFShape *shape, u32 *bits_fill, u32 *bits_line)
     378             : {
     379             :         u32 i, j, count;
     380             :         SWFShapeRec *style;
     381             : 
     382        1427 :         swf_align(read);
     383             : 
     384             :         /*get fill styles*/
     385        1427 :         count = swf_read_int(read, 8);
     386        1427 :         if (revision && (count== 0xFF)) count = swf_get_16(read);
     387        1427 :         if (count) {
     388        1515 :                 for (i=0; i<count; i++) {
     389        1515 :                         style = swf_new_shape_rec();
     390             : 
     391        1515 :                         style->solid_col = 0xFF00FF00;
     392        3030 :                         style->type = swf_read_int(read, 8);
     393             : 
     394             :                         /*gradient fill*/
     395        1515 :                         if (style->type & 0x10) {
     396         206 :                                 swf_get_matrix(read, &style->mat);
     397         206 :                                 swf_align(read);
     398         412 :                                 style->nbGrad = swf_read_int(read, 8);
     399         206 :                                 if (style->nbGrad) {
     400         206 :                                         style->grad_col = (u32 *) gf_malloc(sizeof(u32) * style->nbGrad);
     401         206 :                                         style->grad_ratio = (u8 *) gf_malloc(sizeof(u8) * style->nbGrad);
     402        1022 :                                         for (j=0; j<style->nbGrad; j++) {
     403        1632 :                                                 style->grad_ratio[j] = swf_read_int(read, 8);
     404         816 :                                                 if (revision==2) style->grad_col[j] = swf_get_argb(read);
     405         804 :                                                 else style->grad_col[j] = swf_get_color(read);
     406             :                                         }
     407         206 :                                         style->solid_col = style->grad_col[0];
     408             : 
     409             :                                         /*make sure we have keys between 0 and 1.0 for BIFS (0 and 255 in swf)*/
     410         206 :                                         if (style->grad_ratio[0] != 0) {
     411             :                                                 u32 *grad_col;
     412             :                                                 u8 *grad_ratio;
     413           0 :                                                 grad_ratio = (u8 *) gf_malloc(sizeof(u8) * (style->nbGrad+1));
     414           0 :                                                 grad_col = (u32 *) gf_malloc(sizeof(u32) * (style->nbGrad+1));
     415           0 :                                                 grad_col[0] = style->grad_col[0];
     416           0 :                                                 grad_ratio[0] = 0;
     417           0 :                                                 for (j=0; j<style->nbGrad; j++) {
     418           0 :                                                         grad_col[j+1] = style->grad_col[j];
     419           0 :                                                         grad_ratio[j+1] = style->grad_ratio[j];
     420             :                                                 }
     421           0 :                                                 gf_free(style->grad_col);
     422           0 :                                                 style->grad_col = grad_col;
     423           0 :                                                 gf_free(style->grad_ratio);
     424           0 :                                                 style->grad_ratio = grad_ratio;
     425           0 :                                                 style->nbGrad++;
     426             :                                         }
     427         206 :                                         if (style->grad_ratio[style->nbGrad-1] != 255) {
     428           0 :                                                 u32 *grad_col = (u32*)gf_malloc(sizeof(u32) * (style->nbGrad+1));
     429           0 :                                                 u8 *grad_ratio = (u8*)gf_malloc(sizeof(u8) * (style->nbGrad+1));
     430           0 :                                                 memcpy(grad_col, style->grad_col, sizeof(u32) * style->nbGrad);
     431           0 :                                                 memcpy(grad_ratio, style->grad_ratio, sizeof(u8) * style->nbGrad);
     432           0 :                                                 grad_col[style->nbGrad] = style->grad_col[style->nbGrad-1];
     433           0 :                                                 grad_ratio[style->nbGrad] = 255;
     434           0 :                                                 gf_free(style->grad_col);
     435           0 :                                                 style->grad_col = grad_col;
     436           0 :                                                 gf_free(style->grad_ratio);
     437           0 :                                                 style->grad_ratio = grad_ratio;
     438           0 :                                                 style->nbGrad++;
     439             :                                         }
     440             : 
     441             :                                 } else {
     442           0 :                                         style->solid_col = 0xFF;
     443             :                                 }
     444             :                         }
     445             :                         /*bitmap fill*/
     446        1309 :                         else if (style->type & 0x40) {
     447           2 :                                 style->img_id = swf_get_16(read);
     448           2 :                                 if (style->img_id == 65535) {
     449           0 :                                         style->img_id = 0;
     450           0 :                                         style->type = 0;
     451           0 :                                         style->solid_col = 0xFF00FFFF;
     452             :                                 }
     453           2 :                                 swf_get_matrix(read, &style->mat);
     454             :                         }
     455             :                         /*solid fill*/
     456             :                         else {
     457        1307 :                                 if (revision==2) style->solid_col = swf_get_argb(read);
     458        1262 :                                 else style->solid_col = swf_get_color(read);
     459             :                         }
     460        1515 :                         gf_list_add(shape->fill_right, style);
     461        1515 :                         style = swf_clone_shape_rec(style);
     462        1515 :                         gf_list_add(shape->fill_left, style);
     463             :                 }
     464             :         }
     465             : 
     466        1427 :         swf_align(read);
     467             :         /*get line styles*/
     468        1427 :         count = swf_read_int(read, 8);
     469        1427 :         if (revision && (count==0xFF)) count = swf_get_16(read);
     470        1427 :         if (count) {
     471         846 :                 for (i=0; i<count; i++) {
     472         846 :                         style = swf_new_shape_rec();
     473         846 :                         gf_list_add(shape->lines, style);
     474         846 :                         style->width = FLT2FIX( swf_get_16(read) * SWF_TWIP_SCALE );
     475         846 :                         if (revision==2) style->solid_col = swf_get_argb(read);
     476         846 :                         else style->solid_col = swf_get_color(read);
     477             :                 }
     478             :         }
     479             : 
     480        1427 :         swf_align(read);
     481        2854 :         *bits_fill = swf_read_int(read, 4);
     482        2854 :         *bits_line = swf_read_int(read, 4);
     483        1427 : }
     484             : 
     485      206915 : static void swf_path_realloc_pts(SWFPath *path, u32 nbPts)
     486             : {
     487      206915 :         if (path)
     488      206915 :                 path->pts = (SFVec2f*)gf_realloc(path->pts, sizeof(SFVec2f) * (path->nbPts + nbPts));
     489      206915 : }
     490             : 
     491      175934 : static void swf_path_add_com(SWFShapeRec *sr, SFVec2f pt, SFVec2f ctr, u32 type)
     492             : {
     493             :         /*not an error*/
     494      175934 :         if (!sr) return;
     495             : 
     496       83509 :         sr->path->types = (u32*)gf_realloc(sr->path->types, sizeof(u32) * (sr->path->nbType+1));
     497             : 
     498       83509 :         sr->path->types[sr->path->nbType] = type;
     499       83509 :         switch (type) {
     500       17170 :         case 2:
     501       17170 :                 swf_path_realloc_pts(sr->path, 2);
     502       17170 :                 sr->path->pts[sr->path->nbPts] = ctr;
     503       17170 :                 sr->path->pts[sr->path->nbPts+1] = pt;
     504       17170 :                 sr->path->nbPts+=2;
     505       17170 :                 break;
     506       66339 :         case 1:
     507             :         default:
     508       66339 :                 swf_path_realloc_pts(sr->path, 1);
     509       66339 :                 sr->path->pts[sr->path->nbPts] = pt;
     510       66339 :                 sr->path->nbPts++;
     511       66339 :                 break;
     512             :         }
     513       83509 :         sr->path->nbType++;
     514             : }
     515             : 
     516        1911 : static void swf_referse_path(SWFPath *path)
     517             : {
     518             :         u32 i, j, pti, ptj;
     519             :         u32 *types;
     520             :         SFVec2f *pts;
     521             : 
     522        1911 :         if (path->nbType<=1) return;
     523             : 
     524        1739 :         types = (u32 *) gf_malloc(sizeof(u32) * path->nbType);
     525        1739 :         pts = (SFVec2f *) gf_malloc(sizeof(SFVec2f) * path->nbPts);
     526             : 
     527             : 
     528             :         /*need first moveTo*/
     529        1739 :         types[0] = 0;
     530        1739 :         pts[0] = path->pts[path->nbPts - 1];
     531        1739 :         pti = path->nbPts - 2;
     532             :         ptj = 1;
     533             :         j=1;
     534             : 
     535       45253 :         for (i=0; i<path->nbType-1; i++) {
     536       43514 :                 types[j] = path->types[path->nbType - i - 1];
     537       43514 :                 switch (types[j]) {
     538        8809 :                 case 2:
     539             :                         assert(ptj<=path->nbPts-2);
     540        8809 :                         pts[ptj] = path->pts[pti];
     541        8809 :                         pts[ptj+1] = path->pts[pti-1];
     542        8809 :                         pti-=2;
     543        8809 :                         ptj+=2;
     544        8809 :                         break;
     545       32519 :                 case 1:
     546             :                         assert(ptj<=path->nbPts-1);
     547       32519 :                         pts[ptj] = path->pts[pti];
     548       32519 :                         pti--;
     549       32519 :                         ptj++;
     550       32519 :                         break;
     551        2186 :                 case 0:
     552             :                         assert(ptj<=path->nbPts-1);
     553        2186 :                         pts[ptj] = path->pts[pti];
     554        2186 :                         pti--;
     555        2186 :                         ptj++;
     556        2186 :                         break;
     557             :                 }
     558       43514 :                 j++;
     559             :         }
     560        1739 :         gf_free(path->pts);
     561        1739 :         path->pts = pts;
     562        1739 :         gf_free(path->types);
     563        1739 :         path->types = types;
     564             : }
     565             : 
     566        4690 : static void swf_free_shape_rec(SWFShapeRec *ptr)
     567             : {
     568        4690 :         if (ptr->grad_col) gf_free(ptr->grad_col);
     569        4690 :         if (ptr->grad_ratio) gf_free(ptr->grad_ratio);
     570        4690 :         if (ptr->path) {
     571        4690 :                 if (ptr->path->pts) gf_free(ptr->path->pts);
     572        4690 :                 if (ptr->path->types) gf_free(ptr->path->types);
     573        4690 :                 if (ptr->path->idx) gf_free(ptr->path->idx);
     574        4690 :                 gf_free(ptr->path);
     575             :         }
     576        4690 :         gf_free(ptr);
     577        4690 : }
     578             : 
     579       10068 : static void swf_reset_rec_list(GF_List *recs)
     580             : {
     581       24820 :         while (gf_list_count(recs)) {
     582        4684 :                 SWFShapeRec *tmp = (SWFShapeRec *)gf_list_get(recs, 0);
     583        4684 :                 gf_list_rem(recs, 0);
     584        4684 :                 swf_free_shape_rec(tmp);
     585             :         }
     586       10068 : }
     587             : 
     588        7044 : static void swf_append_path(SWFPath *a, SWFPath *b)
     589             : {
     590        7044 :         if (b->nbType<=1) return;
     591             : 
     592        6872 :         a->pts = (SFVec2f*)gf_realloc(a->pts, sizeof(SFVec2f) * (a->nbPts + b->nbPts));
     593        6872 :         memcpy(&a->pts[a->nbPts], b->pts, sizeof(SFVec2f)*b->nbPts);
     594        6872 :         a->nbPts += b->nbPts;
     595             : 
     596        6872 :         a->types = (u32*)gf_realloc(a->types, sizeof(u32)*(a->nbType+ b->nbType));
     597        6872 :         memcpy(&a->types[a->nbType], b->types, sizeof(u32)*b->nbType);
     598        6872 :         a->nbType += b->nbType;
     599             : }
     600             : 
     601      123406 : static void swf_path_add_type(SWFPath *path, u32 val)
     602             : {
     603      123406 :         path->types = (u32*)gf_realloc(path->types, sizeof(u32) * (path->nbType + 1));
     604      123406 :         path->types[path->nbType] = val;
     605      123406 :         path->nbType++;
     606      123406 : }
     607             : 
     608        2757 : static void swf_resort_path(SWFPath *a, SWFReader *read)
     609             : {
     610             :         u32 idx, i, j;
     611             :         GF_List *paths;
     612             :         SWFPath *sorted, *p, *np;
     613             : 
     614        2757 :         if (!a->nbType) return;
     615             : 
     616        2751 :         paths = gf_list_new();
     617        2751 :         GF_SAFEALLOC(sorted, SWFPath);
     618        2751 :         if (!sorted) {
     619           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_PARSER, ("[SWF Parsing] Fail to allocate path for resorting\n"));
     620             :                 return;
     621             :         }
     622        2751 :         swf_path_realloc_pts(sorted, 1);
     623        2751 :         sorted->pts[sorted->nbPts] = a->pts[0];
     624        2751 :         sorted->nbPts++;
     625        2751 :         swf_path_add_type(sorted, 0);
     626        2751 :         gf_list_add(paths, sorted);
     627             : 
     628             :         /*1- split all paths*/
     629             :         idx = 1;
     630       80752 :         for (i=1; i<a->nbType; i++) {
     631       80752 :                 switch (a->types[i]) {
     632       17170 :                 case 2:
     633       17170 :                         swf_path_realloc_pts(sorted, 2);
     634       17170 :                         sorted->pts[sorted->nbPts] = a->pts[idx];
     635       17170 :                         sorted->pts[sorted->nbPts+1] = a->pts[idx+1];
     636       17170 :                         sorted->nbPts+=2;
     637       17170 :                         swf_path_add_type(sorted, 2);
     638       17170 :                         idx += 2;
     639             :                         break;
     640       58491 :                 case 1:
     641       58491 :                         swf_path_realloc_pts(sorted, 1);
     642       58491 :                         sorted->pts[sorted->nbPts] = a->pts[idx];
     643       58491 :                         sorted->nbPts+=1;
     644       58491 :                         swf_path_add_type(sorted, 1);
     645       58491 :                         idx += 1;
     646             :                         break;
     647        5091 :                 case 0:
     648        5091 :                         GF_SAFEALLOC(sorted , SWFPath);
     649        5091 :                         if (!sorted) return;
     650        5091 :                         swf_path_realloc_pts(sorted, 1);
     651        5091 :                         sorted->pts[sorted->nbPts] = a->pts[idx];
     652        5091 :                         sorted->nbPts++;
     653        5091 :                         swf_path_add_type(sorted, 0);
     654        5091 :                         gf_list_add(paths, sorted);
     655        5091 :                         idx += 1;
     656             :                         break;
     657             :                 }
     658             :         }
     659             : 
     660        5004 : restart:
     661       11865 :         for (i=0; i<gf_list_count(paths); i++) {
     662        9114 :                 p = (SWFPath*)gf_list_get(paths, i);
     663             : 
     664       37605 :                 for (j=i+1; j < gf_list_count(paths); j++) {
     665       30744 :                         np = (SWFPath*)gf_list_get(paths, j);
     666             : 
     667             :                         /*check if any next subpath ends at the same place we're starting*/
     668       30744 :                         if ((np->pts[np->nbPts-1].x == p->pts[0].x) && (np->pts[np->nbPts-1].y == p->pts[0].y)) {
     669             :                                 u32 k;
     670             :                                 idx = 1;
     671       32036 :                                 for (k=1; k<p->nbType; k++) {
     672       32036 :                                         switch (p->types[k]) {
     673        2206 :                                         case 2:
     674        2206 :                                                 swf_path_realloc_pts(np, 2);
     675        2206 :                                                 np->pts[np->nbPts] = p->pts[idx];
     676        2206 :                                                 np->pts[np->nbPts+1] = p->pts[idx+1];
     677        2206 :                                                 np->nbPts+=2;
     678        2206 :                                                 swf_path_add_type(np, 2);
     679        2206 :                                                 idx += 2;
     680             :                                                 break;
     681       29830 :                                         case 1:
     682       29830 :                                                 swf_path_realloc_pts(np, 1);
     683       29830 :                                                 np->pts[np->nbPts] = p->pts[idx];
     684       29830 :                                                 np->nbPts+=1;
     685       29830 :                                                 swf_path_add_type(np, 1);
     686       29830 :                                                 idx += 1;
     687             :                                                 break;
     688             :                                         default:
     689             :                                                 assert(0);
     690             :                                                 break;
     691             :                                         }
     692             :                                 }
     693        2253 :                                 gf_free(p->pts);
     694        2253 :                                 gf_free(p->types);
     695        2253 :                                 gf_free(p);
     696        2253 :                                 gf_list_rem(paths, i);
     697             :                                 goto restart;
     698             :                         }
     699             :                         /*check if any next subpath starts at the same place we're ending*/
     700       28491 :                         else if ((p->pts[p->nbPts-1].x == np->pts[0].x) && (p->pts[p->nbPts-1].y == np->pts[0].y)) {
     701             :                                 u32 k;
     702             :                                 idx = 1;
     703        7867 :                                 for (k=1; k<np->nbType; k++) {
     704        7867 :                                         switch (np->types[k]) {
     705         242 :                                         case 2:
     706         242 :                                                 swf_path_realloc_pts(p, 2);
     707         242 :                                                 p->pts[p->nbPts] = np->pts[idx];
     708         242 :                                                 p->pts[p->nbPts+1] = np->pts[idx+1];
     709         242 :                                                 p->nbPts+=2;
     710         242 :                                                 swf_path_add_type(p, 2);
     711         242 :                                                 idx += 2;
     712             :                                                 break;
     713        7625 :                                         case 1:
     714        7625 :                                                 swf_path_realloc_pts(p, 1);
     715        7625 :                                                 p->pts[p->nbPts] = np->pts[idx];
     716        7625 :                                                 p->nbPts+=1;
     717        7625 :                                                 swf_path_add_type(p, 1);
     718        7625 :                                                 idx += 1;
     719             :                                                 break;
     720             :                                         default:
     721             :                                                 assert(0);
     722             :                                                 break;
     723             :                                         }
     724             :                                 }
     725         456 :                                 gf_free(np->pts);
     726         456 :                                 gf_free(np->types);
     727         456 :                                 gf_free(np);
     728         456 :                                 gf_list_rem(paths, j);
     729         456 :                                 j--;
     730             :                         }
     731             :                 }
     732             :         }
     733             : 
     734             :         /*reassemble path*/
     735        2751 :         gf_free(a->pts);
     736        2751 :         gf_free(a->types);
     737             :         memset(a, 0, sizeof(SWFPath));
     738             : 
     739        7884 :         while (gf_list_count(paths)) {
     740        5133 :                 sorted = (SWFPath*)gf_list_get(paths, 0);
     741        5133 :                 if (read->flat_limit==0) {
     742        5133 :                         swf_append_path(a, sorted);
     743             :                 } else {
     744             :                         Bool prev_is_line_to = 0;
     745             :                         idx = 0;
     746           0 :                         for (i=0; i<sorted->nbType; i++) {
     747           0 :                                 switch (sorted->types[i]) {
     748           0 :                                 case 2:
     749           0 :                                         swf_path_realloc_pts(a, 2);
     750           0 :                                         a->pts[a->nbPts] = sorted->pts[idx];
     751           0 :                                         a->pts[a->nbPts+1] = sorted->pts[idx+1];
     752           0 :                                         a->nbPts+=2;
     753           0 :                                         swf_path_add_type(a, 2);
     754           0 :                                         idx += 2;
     755             :                                         prev_is_line_to = 0;
     756             :                                         break;
     757           0 :                                 case 1:
     758           0 :                                         if (prev_is_line_to) {
     759             :                                                 Fixed angle;
     760             :                                                 Bool flatten = 0;
     761             :                                                 SFVec2f v1, v2;
     762           0 :                                                 v1.x = a->pts[a->nbPts-1].x - a->pts[a->nbPts-2].x;
     763           0 :                                                 v1.y = a->pts[a->nbPts-1].y - a->pts[a->nbPts-2].y;
     764           0 :                                                 v2.x = a->pts[a->nbPts-1].x - sorted->pts[idx].x;
     765           0 :                                                 v2.y = a->pts[a->nbPts-1].y - sorted->pts[idx].y;
     766             : 
     767           0 :                                                 angle = gf_mulfix(v1.x,v2.x) + gf_mulfix(v1.y,v2.y);
     768             :                                                 /*get magnitudes*/
     769           0 :                                                 v1.x = gf_v2d_len(&v1);
     770           0 :                                                 v2.x = gf_v2d_len(&v2);
     771           0 :                                                 if (!v1.x || !v2.x) flatten = 1;
     772             :                                                 else {
     773             :                                                         Fixed h_pi = GF_PI / 2;
     774           0 :                                                         angle = gf_divfix(angle, gf_mulfix(v1.x, v2.x));
     775           0 :                                                         if (angle + FIX_EPSILON >= FIX_ONE) angle = 0;
     776           0 :                                                         else if (angle - FIX_EPSILON <= -FIX_ONE) angle = GF_PI;
     777           0 :                                                         else angle = gf_acos(angle);
     778             : 
     779             :                                                         if (angle<0) angle += h_pi;
     780           0 :                                                         angle = ABSDIFF(angle, h_pi);
     781           0 :                                                         if (angle < read->flat_limit) flatten = 1;
     782             :                                                 }
     783             :                                                 if (flatten) {
     784           0 :                                                         a->pts[a->nbPts-1] = sorted->pts[idx];
     785           0 :                                                         idx++;
     786           0 :                                                         read->flatten_points++;
     787           0 :                                                         break;
     788             :                                                 }
     789             :                                         }
     790           0 :                                         swf_path_realloc_pts(a, 1);
     791           0 :                                         a->pts[a->nbPts] = sorted->pts[idx];
     792           0 :                                         a->nbPts+=1;
     793           0 :                                         swf_path_add_type(a, 1);
     794           0 :                                         idx += 1;
     795             :                                         prev_is_line_to = 1;
     796             :                                         break;
     797           0 :                                 case 0:
     798           0 :                                         swf_path_realloc_pts(a, 1);
     799           0 :                                         a->pts[a->nbPts] = sorted->pts[idx];
     800           0 :                                         a->nbPts+=1;
     801           0 :                                         swf_path_add_type(a, 0);
     802           0 :                                         idx += 1;
     803             :                                         prev_is_line_to = 0;
     804             :                                         break;
     805             :                                 }
     806             :                         }
     807             :                 }
     808        5133 :                 gf_free(sorted->pts);
     809        5133 :                 gf_free(sorted->types);
     810        5133 :                 gf_free(sorted);
     811        5133 :                 gf_list_rem(paths, 0);
     812             :         }
     813        2751 :         gf_list_del(paths);
     814             : }
     815             : 
     816             : /*
     817             :         Notes on SWF->BIFS conversion - some ideas taken from libswfdec
     818             :         A single fillStyle has 2 associated path, one used for left fill, one for right fill
     819             :         This is then a 4 step process:
     820             :         1- blindly parse swf shape, and add point/lines to the proper left/right path
     821             :         2- for each fillStyles, revert the right path so that it becomes a left path
     822             :         3- concatenate left and right paths
     823             :         4- resort all subelements of the final path, making sure moveTo introduced by the SWF coding (due to style changes)
     824             :         are removed.
     825             :                 Ex: if path is
     826             :                         A->C, B->A, C->B = moveTo(A), lineTo(C), moveTo(B), lineTo (A), moveTo(C), lineTo(B)
     827             :                 we restort and remove unneeded moves to get
     828             :                         A->C->B = moveTo(A), lineTo(C), lineTo(B), lineTo(A)
     829             : */
     830        1834 : static GF_Err swf_flush_shape(SWFReader *read, SWFShape *shape, SWFFont *font, Bool last_shape)
     831             : {
     832             :         GF_Err e;
     833             :         SWFShapeRec *sf0;
     834             :         u32 i, count;
     835        1834 :         count = gf_list_count(shape->fill_left);
     836        3745 :         for (i=0; i<count; i++) {
     837             :                 SWFShapeRec *sf1;
     838        1911 :                 sf0 = (SWFShapeRec*)gf_list_get(shape->fill_left, i);
     839        1911 :                 sf1 = (SWFShapeRec*)gf_list_get(shape->fill_right, i);
     840             :                 /*reverse right path*/
     841        1911 :                 swf_referse_path(sf1->path);
     842             :                 /*concatenate with left path*/
     843        1911 :                 swf_append_path(sf0->path, sf1->path);
     844             :                 /*resort all path curves*/
     845        1911 :                 swf_resort_path(sf0->path, read);
     846             :         }
     847             :         /*remove dummy fill_left*/
     848        1911 :         for (i=0; i<gf_list_count(shape->fill_left); i++) {
     849        1911 :                 sf0 = (SWFShapeRec*)gf_list_get(shape->fill_left, i);
     850        1911 :                 if (sf0->path->nbType<=1) {
     851           6 :                         gf_list_rem(shape->fill_left, i);
     852           6 :                         swf_free_shape_rec(sf0);
     853           6 :                         i--;
     854             :                 }
     855             :         }
     856             :         /*remove dummy lines*/
     857         846 :         for (i=0; i<gf_list_count(shape->lines); i++) {
     858         846 :                 SWFShapeRec *sl = (SWFShapeRec*)gf_list_get(shape->lines, i);
     859         846 :                 if (sl->path->nbType<1) {
     860           0 :                         gf_list_rem(shape->lines, i);
     861           0 :                         swf_free_shape_rec(sl);
     862           0 :                         i--;
     863             :                 } else {
     864         846 :                         swf_resort_path(sl->path, read);
     865             :                 }
     866             :         }
     867             : 
     868             :         /*now translate a flash shape record into BIFS*/
     869        1834 :         e = read->define_shape(read, shape, font, last_shape);
     870             : 
     871             :         /*delete shape*/
     872        1834 :         swf_reset_rec_list(shape->fill_left);
     873        1834 :         swf_reset_rec_list(shape->fill_right);
     874        1834 :         swf_reset_rec_list(shape->lines);
     875        1834 :         return e;
     876             : }
     877             : 
     878        1511 : static GF_Err swf_parse_shape_def(SWFReader *read, SWFFont *font, u32 revision)
     879             : {
     880             :         u32 nbBits, comType;
     881             :         s32 x, y;
     882             :         SFVec2f orig, ctrl, end;
     883             :         Bool flag;
     884             :         u32 fill0, fill1, strike;
     885             :         u32 bits_fill, bits_line;
     886             :         SWFShape shape;
     887             :         Bool is_empty;
     888             :         SWFShapeRec *sf0, *sf1, *sl;
     889             : 
     890             :         memset(&shape, 0, sizeof(SWFShape));
     891        1511 :         shape.fill_left = gf_list_new();
     892        1511 :         shape.fill_right = gf_list_new();
     893        1511 :         shape.lines = gf_list_new();
     894        1511 :         ctrl.x = ctrl.y = 0;
     895        1511 :         swf_align(read);
     896             : 
     897             :         /*regular shape - get initial styles*/
     898        1511 :         if (!font) {
     899        1104 :                 shape.ID = swf_get_16(read);
     900        1104 :                 swf_get_rec(read, &shape.rc);
     901        1104 :                 swf_parse_styles(read, revision, &shape, &bits_fill, &bits_line);
     902             :         }
     903             :         /*glyph*/
     904             :         else {
     905         814 :                 bits_fill = swf_read_int(read, 4);
     906         814 :                 bits_line = swf_read_int(read, 4);
     907             : 
     908             :                 /*fonts are usually defined without styles*/
     909         407 :                 if ((read->tag == SWF_DEFINEFONT) || (read->tag==SWF_DEFINEFONT2)) {
     910         407 :                         sf0 = swf_new_shape_rec();
     911         407 :                         gf_list_add(shape.fill_right, sf0);
     912         407 :                         sf0 = swf_new_shape_rec();
     913         407 :                         gf_list_add(shape.fill_left, sf0);
     914         407 :                         sf0->solid_col = 0xFF000000;
     915         407 :                         sf0->type = 0;
     916             :                 }
     917             :         }
     918             : 
     919             :         is_empty = 1;
     920             : 
     921             :         /*parse all points*/
     922             :         fill0 = fill1 = strike = 0;
     923             :         sf0 = sf1 = sl = NULL;
     924             :         x = y = 0;
     925             :         while (1) {
     926       61736 :                 flag = swf_read_int(read, 1);
     927       61736 :                 if (!flag) {
     928        8586 :                         Bool new_style = swf_read_int(read, 1);
     929        8586 :                         Bool set_strike = swf_read_int(read, 1);
     930        8586 :                         Bool set_fill1 = swf_read_int(read, 1);
     931        8586 :                         Bool set_fill0 = swf_read_int(read, 1);
     932        8586 :                         Bool move_to = swf_read_int(read, 1);
     933             :                         /*end of shape*/
     934        8586 :                         if (!new_style && !set_strike && !set_fill0 && !set_fill1 && !move_to) break;
     935             : 
     936             :                         is_empty = 0;
     937             : 
     938        7075 :                         if (move_to) {
     939        4512 :                                 nbBits = swf_read_int(read, 5);
     940        4512 :                                 x = swf_read_sint(read, nbBits);
     941        4512 :                                 y = swf_read_sint(read, nbBits);
     942             :                         }
     943        7075 :                         if (set_fill0) fill0 = swf_read_int(read, bits_fill);
     944        7075 :                         if (set_fill1) fill1 = swf_read_int(read, bits_fill);
     945        7075 :                         if (set_strike) strike = swf_read_int(read, bits_line);
     946             :                         /*looks like newStyle does not append styles but define a new set - old styles can no
     947             :                         longer be referenced*/
     948        7075 :                         if (new_style) {
     949             :                                 /*flush current shape record into BIFS*/
     950         323 :                                 swf_flush_shape(read, &shape, font, 0);
     951         323 :                                 swf_parse_styles(read, revision, &shape, &bits_fill, &bits_line);
     952             :                         }
     953             : 
     954        7075 :                         if (read->flags & GF_SM_SWF_NO_LINE) strike = 0;
     955             : 
     956             :                         /*moveto*/
     957        7075 :                         orig.x = FLT2FIX( x * SWF_TWIP_SCALE );
     958        7075 :                         orig.y = FLT2FIX( y * SWF_TWIP_SCALE );
     959        7075 :                         end = orig;
     960             : 
     961        7075 :                         sf0 = fill0 ? (SWFShapeRec*)gf_list_get(shape.fill_left, fill0 - 1) : NULL;
     962        7075 :                         sf1 = fill1 ? (SWFShapeRec*)gf_list_get(shape.fill_right, fill1 - 1) : NULL;
     963        7075 :                         sl = strike ? (SWFShapeRec*)gf_list_get(shape.lines, strike - 1) : NULL;
     964             : 
     965        7075 :                         if (move_to) {
     966        4512 :                                 swf_path_add_com(sf0, end, ctrl, 0);
     967        4512 :                                 swf_path_add_com(sf1, end, ctrl, 0);
     968        4512 :                                 swf_path_add_com(sl, end, ctrl, 0);
     969             :                         } else {
     970        2563 :                                 if (set_fill0) swf_path_add_com(sf0, end, ctrl, 0);
     971        2563 :                                 if (set_fill1) swf_path_add_com(sf1, end, ctrl, 0);
     972        2563 :                                 if (set_strike) swf_path_add_com(sl, end, ctrl, 0);
     973             :                         }
     974             : 
     975             :                 } else {
     976       53150 :                         flag = swf_read_int(read, 1);
     977             :                         /*quadratic curve*/
     978       53150 :                         if (!flag) {
     979       25426 :                                 nbBits = 2 + swf_read_int(read, 4);
     980       12713 :                                 x += swf_read_sint(read, nbBits);
     981       12713 :                                 y += swf_read_sint(read, nbBits);
     982       12713 :                                 ctrl.x = FLT2FIX( x * SWF_TWIP_SCALE );
     983       12713 :                                 ctrl.y = FLT2FIX( y * SWF_TWIP_SCALE );
     984       12713 :                                 x += swf_read_sint(read, nbBits);
     985       12713 :                                 y += swf_read_sint(read, nbBits);
     986       12713 :                                 end.x = FLT2FIX( x * SWF_TWIP_SCALE );
     987       12713 :                                 end.y = FLT2FIX( y * SWF_TWIP_SCALE );
     988             :                                 /*curveTo*/
     989             :                                 comType = 2;
     990             :                         }
     991             :                         /*straight line*/
     992             :                         else {
     993       80874 :                                 nbBits = 2 + swf_read_int(read, 4);
     994       40437 :                                 flag = swf_read_int(read, 1);
     995       40437 :                                 if (flag) {
     996       19262 :                                         x += swf_read_sint(read, nbBits);
     997       19262 :                                         y += swf_read_sint(read, nbBits);
     998             :                                 } else {
     999       21175 :                                         flag = swf_read_int(read, 1);
    1000       21175 :                                         if (flag) {
    1001       11321 :                                                 y += swf_read_sint(read, nbBits);
    1002             :                                         } else {
    1003        9854 :                                                 x += swf_read_sint(read, nbBits);
    1004             :                                         }
    1005             :                                 }
    1006             :                                 /*lineTo*/
    1007             :                                 comType = 1;
    1008       40437 :                                 end.x = FLT2FIX( x * SWF_TWIP_SCALE );
    1009       40437 :                                 end.y = FLT2FIX( y * SWF_TWIP_SCALE );
    1010             :                         }
    1011       53150 :                         swf_path_add_com(sf0, end, ctrl, comType);
    1012       53150 :                         swf_path_add_com(sf1, end, ctrl, comType);
    1013       53150 :                         swf_path_add_com(sl, end, ctrl, comType);
    1014             :                 }
    1015             :         }
    1016             : 
    1017        1511 :         if (is_empty) {
    1018          11 :                 swf_reset_rec_list(shape.fill_left);
    1019          11 :                 swf_reset_rec_list(shape.fill_right);
    1020          11 :                 swf_reset_rec_list(shape.lines);
    1021             :         }
    1022             : 
    1023        1511 :         swf_align(read);
    1024             : 
    1025             :         /*now translate a flash shape record*/
    1026        1511 :         swf_flush_shape(read, &shape, font, 1);
    1027             : 
    1028             :         /*delete shape*/
    1029        1511 :         swf_reset_rec_list(shape.fill_left);
    1030        1511 :         swf_reset_rec_list(shape.fill_right);
    1031        1511 :         swf_reset_rec_list(shape.lines);
    1032        1511 :         gf_list_del(shape.fill_left);
    1033        1511 :         gf_list_del(shape.fill_right);
    1034        1511 :         gf_list_del(shape.lines);
    1035             : 
    1036        1511 :         return GF_OK;
    1037             : }
    1038             : 
    1039         384 : SWFFont *swf_find_font(SWFReader *read, u32 ID)
    1040             : {
    1041             :         u32 i, count;
    1042         384 :         count = gf_list_count(read->fonts);
    1043         462 :         for (i=0; i<count; i++) {
    1044         462 :                 SWFFont *ft = (SWFFont *)gf_list_get(read->fonts, i);
    1045         462 :                 if (ft->fontID==ID) return ft;
    1046             :         }
    1047             :         return NULL;
    1048             : }
    1049             : 
    1050       10673 : static DispShape *swf_get_depth_entry(SWFReader *read, u32 Depth, Bool create)
    1051             : {
    1052             :         u32 i;
    1053             :         DispShape *tmp;
    1054       10673 :         i=0;
    1055      106363 :         while ((tmp = (DispShape *)gf_list_enum(read->display_list, &i))) {
    1056      106187 :                 if (tmp->depth == Depth) return tmp;
    1057             :         }
    1058         176 :         if (!create) return NULL;
    1059         172 :         GF_SAFEALLOC(tmp , DispShape);
    1060         172 :         if (!tmp) return NULL;
    1061         172 :         tmp->depth = Depth;
    1062         172 :         tmp->char_id = 0;
    1063         172 :         gf_list_add(read->display_list, tmp);
    1064             : 
    1065         172 :         memset(&tmp->mat, 0, sizeof(GF_Matrix2D));
    1066         172 :         tmp->mat.m[0] = tmp->mat.m[4] = FIX_ONE;
    1067             : 
    1068         172 :         memset(&tmp->cmat, 0, sizeof(GF_ColorMatrix));
    1069         172 :         tmp->cmat.m[0] = tmp->cmat.m[6] = tmp->cmat.m[12] = tmp->cmat.m[18] = FIX_ONE;
    1070         172 :         tmp->cmat.identity = 1;
    1071             :         return tmp;
    1072             : }
    1073             : 
    1074             : 
    1075           0 : static GF_Err swf_func_skip(SWFReader *read)
    1076             : {
    1077           0 :         if (!read) return GF_OK;
    1078           0 :         swf_skip_data(read, read->size);
    1079           0 :         return read->ioerr;
    1080             : }
    1081             : 
    1082             : static GF_Err swf_set_backcol(SWFReader *read)
    1083             : {
    1084          13 :         u32 col = swf_get_color(read);
    1085          13 :         return read->set_backcol(read, col);
    1086             : }
    1087             : 
    1088          18 : static GF_Err swf_actions(SWFReader *read, u32 mask, u32 key)
    1089             : {
    1090             :         u32 skip_actions = 0;
    1091          36 :         u8 action_code = swf_read_int(read, 8);
    1092          18 :         read->has_interact = 1;
    1093             : 
    1094             : 
    1095             : #define DO_ACT(_code) { act.type = _code; read->action(read, &act); break; }
    1096             : 
    1097         105 :         while (action_code) {
    1098             :                 u16 length;
    1099          69 :                 if (action_code > 0x80) length = swf_get_16(read);
    1100             :                 else length = 0;
    1101             : 
    1102          69 :                 if (read->no_as || skip_actions) {
    1103           0 :                         swf_skip_data(read, length);
    1104           0 :                         if (skip_actions) skip_actions--;
    1105             :                 } else {
    1106             :                         SWFAction act;
    1107             :                         memset(&act, 0, sizeof(SWFAction));
    1108          69 :                         act.button_mask = mask;
    1109          69 :                         act.button_key = key;
    1110             : 
    1111          69 :                         switch (action_code) {
    1112             :                         /* SWF 3 Action Model */
    1113           7 :                         case 0x81: /* goto frame */
    1114             :                                 assert (length == 2);
    1115             :                                 act.type = GF_SWF_AS3_GOTO_FRAME;
    1116           7 :                                 act.frame_number = swf_get_16(read);
    1117           7 :                                 read->action(read, &act);
    1118           7 :                                 break;
    1119           2 :                         case 0x83: /* get URL */
    1120           2 :                                 act.type = GF_SWF_AS3_GET_URL;
    1121           2 :                                 act.url = swf_get_string(read);
    1122           2 :                                 act.target = swf_get_string(read);
    1123           2 :                                 read->action(read, &act);
    1124           2 :                                 gf_free(act.url);
    1125           2 :                                 gf_free(act.target);
    1126           2 :                                 break;
    1127             :                         /* next frame */
    1128           0 :                         case 0x04:
    1129           0 :                                 DO_ACT(GF_SWF_AS3_NEXT_FRAME)
    1130             :                         /* previous frame */
    1131           0 :                         case 0x05:
    1132           0 :                                 DO_ACT(GF_SWF_AS3_PREV_FRAME)
    1133             :                         /* play */
    1134           7 :                         case 0x06:
    1135           7 :                                 DO_ACT(GF_SWF_AS3_PLAY)
    1136             :                         /* stop */
    1137           5 :                         case 0x07:
    1138           5 :                                 DO_ACT(GF_SWF_AS3_STOP)
    1139             :                         /* toggle quality */
    1140           0 :                         case 0x08:
    1141           0 :                                 DO_ACT(GF_SWF_AS3_TOGGLE_QUALITY)
    1142             :                         /* stop sounds*/
    1143           0 :                         case 0x09:
    1144           0 :                                 DO_ACT(GF_SWF_AS3_STOP_SOUNDS)
    1145             :                         /* wait for frame */
    1146           2 :                         case 0x8A:
    1147             :                                 assert (length == 3);
    1148           2 :                                 act.type = GF_SWF_AS3_WAIT_FOR_FRAME;
    1149           2 :                                 act.frame_number = swf_get_16(read);
    1150           2 :                                 skip_actions = swf_read_int(read, 8);
    1151           2 :                                 if (read->action(read, &act)) skip_actions = 0;
    1152             :                                 break;
    1153             :                         /* set target */
    1154           0 :                         case 0x8B:
    1155           0 :                                 act.type = GF_SWF_AS3_SET_TARGET;
    1156           0 :                                 act.target = swf_get_string(read);
    1157           0 :                                 read->action(read, &act);
    1158           0 :                                 gf_free(act.target);
    1159           0 :                                 break;
    1160             :                         /* goto label */
    1161           0 :                         case 0x8C:
    1162           0 :                                 act.type = GF_SWF_AS3_GOTO_LABEL;
    1163           0 :                                 act.target = swf_get_string(read);
    1164           0 :                                 read->action(read, &act);
    1165           0 :                                 gf_free(act.target);
    1166           0 :                                 break;
    1167          46 :                         default:
    1168             : //                              swf_report(read, GF_OK, "Skipping unsupported action %x", action_code);
    1169          46 :                                 if (length) swf_skip_data(read, length);
    1170             :                                 break;
    1171             :                         }
    1172             :                 }
    1173         138 :                 action_code = swf_read_int(read, 8);
    1174             :         }
    1175             : #undef DO_ACT
    1176             : 
    1177          18 :         return GF_OK;
    1178             : }
    1179             : 
    1180           8 : static GF_Err swf_def_button(SWFReader *read, u32 revision)
    1181             : {
    1182             :         SWF_Button button;
    1183             :         Bool has_actions;
    1184             : 
    1185             :         memset(&button, 0, sizeof(SWF_Button));
    1186             :         has_actions = 0;
    1187             :         button.count = 0;
    1188           8 :         button.ID = swf_get_16(read);
    1189           8 :         if (revision==1) {
    1190           8 :                 gf_bs_read_int(read->bs, 7);
    1191           8 :                 gf_bs_read_int(read->bs, 1);
    1192           8 :                 has_actions = swf_get_16(read);
    1193             :         }
    1194          44 :         while (1) {
    1195          52 :                 SWF_ButtonRecord *rec = &button.buttons[button.count];
    1196          52 :                 gf_bs_read_int(read->bs, 4);
    1197          52 :                 rec->hitTest = gf_bs_read_int(read->bs, 1);
    1198          52 :                 rec->down = gf_bs_read_int(read->bs, 1);
    1199          52 :                 rec->over = gf_bs_read_int(read->bs, 1);
    1200          52 :                 rec->up = gf_bs_read_int(read->bs, 1);
    1201          52 :                 if (!rec->hitTest && !rec->up && !rec->over && !rec->down) break;
    1202          44 :                 rec->character_id = swf_get_16(read);
    1203          44 :                 rec->depth = swf_get_16(read);
    1204          44 :                 swf_get_matrix(read, &rec->mx);
    1205          44 :                 if (revision==1) {
    1206          44 :                         swf_align(read);
    1207          44 :                         swf_get_colormatrix(read, &rec->cmx);
    1208             :                 }
    1209           0 :                 else gf_cmx_init(&rec->cmx);
    1210          44 :                 gf_bs_align(read->bs);
    1211          44 :                 button.count++;
    1212             :         }
    1213           8 :         read->define_button(read, &button);
    1214           8 :         if (revision==0) {
    1215           0 :                 swf_actions(read, GF_SWF_COND_OVERUP_TO_OVERDOWN, 0);
    1216             :         } else {
    1217          14 :                 while (has_actions) {
    1218             :                         u32 i, mask, key;
    1219           6 :                         has_actions = swf_get_16(read);
    1220             :                         mask = 0;
    1221          54 :                         for (i=0; i<8; i++) {
    1222          96 :                                 if (swf_read_int(read, 1))
    1223           6 :                                         mask |= 1<<i;
    1224             :                         }
    1225           6 :                         key = swf_read_int(read, 7);
    1226          12 :                         if (swf_read_int(read, 1))
    1227           0 :                                 mask |= GF_SWF_COND_OVERDOWN_TO_IDLE;
    1228             : 
    1229           6 :                         swf_actions(read, mask, key);
    1230             :                 }
    1231             :         }
    1232           8 :         read->define_button(read, NULL);
    1233           8 :         return GF_OK;
    1234             : }
    1235             : 
    1236             : static Bool swf_mat_is_identity(GF_Matrix2D *mat)
    1237             : {
    1238       10718 :         if (mat->m[0] != FIX_ONE) return 0;
    1239        2433 :         if (mat->m[4] != FIX_ONE) return 0;
    1240        2415 :         if (mat->m[1]) return 0;
    1241        2415 :         if (mat->m[2]) return 0;
    1242         461 :         if (mat->m[3]) return 0;
    1243         461 :         if (mat->m[5]) return 0;
    1244             :         return 1;
    1245             : }
    1246             : 
    1247        5388 : static GF_Err swf_place_obj(SWFReader *read, u32 revision)
    1248             : {
    1249             :         GF_Err e;
    1250             :         u32 shape_id;
    1251             :         u32 ID, bitsize;
    1252             :         u32 clip_depth;
    1253             :         GF_Matrix2D mat;
    1254             :         GF_ColorMatrix cmat;
    1255             :         DispShape *ds;
    1256             :         char *name;
    1257             :         u32 depth, type;
    1258             :         Bool had_depth;
    1259             :         /*SWF flags*/
    1260             :         Bool has_clip_actions, has_clip, has_name, has_ratio, has_cmat, has_mat, has_id, has_move;
    1261             : 
    1262             :         name = NULL;
    1263             :         clip_depth = 0;
    1264             :         ID = 0;
    1265             :         depth = 0;
    1266             :         has_cmat = has_mat = has_move = 0;
    1267             : 
    1268        5388 :         gf_cmx_init(&cmat);
    1269        5388 :         gf_mx2d_init(mat);
    1270             :         /*place*/
    1271             :         type = SWF_PLACE;
    1272             : 
    1273             :         /*SWF 1.0*/
    1274        5388 :         if (revision==0) {
    1275           0 :                 ID = swf_get_16(read);
    1276           0 :                 depth = swf_get_16(read);
    1277             :                 bitsize = 32;
    1278           0 :                 bitsize += swf_get_matrix(read, &mat);
    1279             :                 has_mat = 1;
    1280           0 :                 bitsize += swf_align(read);
    1281             :                 /*size exceeds matrix, parse col mat*/
    1282           0 :                 if (bitsize < read->size*8) {
    1283           0 :                         swf_get_colormatrix(read, &cmat);
    1284             :                         has_cmat = 1;
    1285           0 :                         swf_align(read);
    1286             :                 }
    1287             :         }
    1288             :         /*SWF 3.0*/
    1289        5388 :         else if (revision==1) {
    1290             :                 /*reserved*/
    1291        5388 :                 has_clip_actions = swf_read_int(read, 1);
    1292        5388 :                 has_clip = swf_read_int(read, 1);
    1293        5388 :                 has_name = swf_read_int(read, 1);
    1294        5388 :                 has_ratio = swf_read_int(read, 1);
    1295        5388 :                 has_cmat = swf_read_int(read, 1);
    1296        5388 :                 has_mat = swf_read_int(read, 1);
    1297        5388 :                 has_id = swf_read_int(read, 1);
    1298        5388 :                 has_move = swf_read_int(read, 1);
    1299             : 
    1300        5388 :                 depth = swf_get_16(read);
    1301        7575 :                 if (has_id) ID = swf_get_16(read);
    1302        5388 :                 if (has_mat) {
    1303        4502 :                         swf_get_matrix(read, &mat);
    1304        4502 :                         swf_align(read);
    1305             :                 }
    1306        5388 :                 if (has_cmat) {
    1307         136 :                         swf_align(read);
    1308         136 :                         swf_get_colormatrix(read, &cmat);
    1309         136 :                         swf_align(read);
    1310             :                 }
    1311        5388 :                 if (has_ratio) /*ratio = */swf_get_16(read);
    1312        5388 :                 if (has_clip) clip_depth = swf_get_16(read);
    1313             : 
    1314        5388 :                 if (has_name) {
    1315           3 :                         name = swf_get_string(read);
    1316           3 :                         gf_free(name);
    1317             :                 }
    1318        5388 :                 if (has_clip_actions) {
    1319             :                         swf_get_16(read);
    1320             :                         swf_get_16(read);
    1321             :                 }
    1322             :                 /*replace*/
    1323        5388 :                 if (has_id && has_move) type = SWF_REPLACE;
    1324             :                 /*move*/
    1325        3897 :                 else if (!has_id && has_move) type = SWF_MOVE;
    1326             :                 /*place*/
    1327             :                 else type = SWF_PLACE;
    1328             :         }
    1329             : 
    1330        5388 :         if (clip_depth) {
    1331           0 :                 swf_report(read, GF_NOT_SUPPORTED, "Clipping not supported - ignoring");
    1332           0 :                 return GF_OK;
    1333             :         }
    1334             : 
    1335             :         /*1: check depth of display list*/
    1336        5388 :         had_depth = read->allocate_depth(read, depth);
    1337             :         /*check validity*/
    1338        5388 :         if ((type==SWF_MOVE) && !had_depth) swf_report(read, GF_BAD_PARAM, "Accessing empty depth level %d", depth);
    1339             : 
    1340             :         ds = NULL;
    1341             : 
    1342             :         /*usual case: (re)place depth level*/
    1343        5388 :         switch (type) {
    1344        3201 :         case SWF_MOVE:
    1345        3201 :                 ds = swf_get_depth_entry(read, depth, 0);
    1346        3201 :                 shape_id = ds ? ds->char_id : 0;
    1347             :                 break;
    1348             :         case SWF_REPLACE:
    1349             :         case SWF_PLACE:
    1350             :         default:
    1351             :                 shape_id = ID;
    1352             :                 break;
    1353             :         }
    1354             : 
    1355        5388 :         if (!shape_id) {
    1356           0 :                 swf_report(read, GF_BAD_PARAM, "%s unfound object (ID %d)", (type==SWF_MOVE) ? "Moving" : ((type==SWF_PLACE) ? "Placing" : "Replacing"), ID);
    1357           0 :                 return GF_OK;
    1358             :         }
    1359             :         /*restore prev matrix if needed*/
    1360        5388 :         if (type==SWF_REPLACE) {
    1361        1491 :                 if (!ds) ds = swf_get_depth_entry(read, depth, 0);
    1362        1491 :                 if (ds) {
    1363        1487 :                         if (!has_mat) {
    1364         828 :                                 memcpy(&mat, &ds->mat, sizeof(GF_Matrix2D));
    1365             :                                 has_mat = 1;
    1366             :                         }
    1367        1487 :                         if (!has_cmat) {
    1368        1391 :                                 memcpy(&cmat, &ds->cmat, sizeof(GF_ColorMatrix));
    1369             :                                 has_cmat = 1;
    1370             :                         }
    1371             :                 }
    1372             :         }
    1373             : 
    1374             :         /*check for identity matrices*/
    1375        3997 :         if (has_cmat && cmat.identity) has_cmat = 0;
    1376        5388 :         if (has_mat && swf_mat_is_identity(&mat)) has_mat = 0;
    1377             : 
    1378             :         /*store in display list*/
    1379        5388 :         ds = swf_get_depth_entry(read, depth, 1);
    1380       15833 :         e = read->place_obj(read, depth, shape_id, ds->char_id, type,
    1381             :                             has_mat ? &mat : NULL,
    1382             :                             has_cmat ? &cmat : NULL,
    1383             :                             swf_mat_is_identity(&ds->mat) ? NULL : &ds->mat,
    1384        5388 :                             ds->cmat.identity ? NULL : &ds->cmat);
    1385             : 
    1386             :         /*remember matrices*/
    1387        5388 :         memcpy(&ds->mat, &mat, sizeof(GF_Matrix2D));
    1388        5388 :         memcpy(&ds->cmat, &cmat, sizeof(GF_ColorMatrix));
    1389        5388 :         ds->char_id = shape_id;
    1390             : 
    1391        5388 :         if (e) swf_report(read, e, "Error %s object ID %d", (type==SWF_MOVE) ? "Moving" : ((type==SWF_PLACE) ? "Placing" : "Replacing"), shape_id);
    1392             :         return GF_OK;
    1393             : }
    1394             : 
    1395         593 : static GF_Err swf_remove_obj(SWFReader *read, u32 revision)
    1396             : {
    1397             :         GF_Err e;
    1398             :         DispShape *ds;
    1399             :         u32 depth;
    1400         593 :         if (revision==0) swf_get_16(read);
    1401         593 :         depth = swf_get_16(read);
    1402         593 :         ds = swf_get_depth_entry(read, depth, 0);
    1403             :         /*this happens if a placeObject has failed*/
    1404         593 :         if (!ds) return GF_OK;
    1405         593 :         e = read->remove_obj(read, depth, ds->char_id);
    1406         593 :         ds->char_id = 0;
    1407         593 :         return e;
    1408             : }
    1409             : 
    1410             : static GF_Err swf_show_frame(SWFReader *read)
    1411             : {
    1412             :         GF_Err e;
    1413        3302 :         e = read->show_frame(read);
    1414        3302 :         read->current_frame ++;
    1415             :         return e;
    1416             : }
    1417             : 
    1418          25 : static GF_Err swf_def_font(SWFReader *read, u32 revision)
    1419             : {
    1420             :         u32 i, count;
    1421             :         GF_Err e;
    1422             :         SWFFont *ft;
    1423             :         u32 *offset_table = NULL;
    1424             :         u32 start;
    1425             : 
    1426          25 :         GF_SAFEALLOC(ft, SWFFont);
    1427          25 :         if (!ft) return GF_OUT_OF_MEM;
    1428             : 
    1429          25 :         ft->glyphs = gf_list_new();
    1430          25 :         ft->fontID = swf_get_16(read);
    1431             :         e = GF_OK;
    1432             : 
    1433             : 
    1434          25 :         if (revision==0) {
    1435          11 :                 start = swf_get_file_pos(read);
    1436             : 
    1437          11 :                 count = swf_get_16(read);
    1438          11 :                 ft->nbGlyphs = count / 2;
    1439          11 :                 offset_table = (u32*)gf_malloc(sizeof(u32) * ft->nbGlyphs);
    1440          11 :                 offset_table[0] = 0;
    1441         285 :                 for (i=1; i<ft->nbGlyphs; i++) offset_table[i] = swf_get_16(read);
    1442             : 
    1443         285 :                 for (i=0; i<ft->nbGlyphs; i++) {
    1444         285 :                         swf_align(read);
    1445         285 :                         e = swf_seek_file_to(read, start + offset_table[i]);
    1446         285 :                         if (e) break;
    1447         285 :                         swf_parse_shape_def(read, ft, 0);
    1448             :                 }
    1449          11 :                 gf_free(offset_table);
    1450          11 :                 if (e) return e;
    1451          14 :         } else if (revision==1) {
    1452             :                 SWFRec rc;
    1453             :                 Bool wide_offset, wide_codes;
    1454             :                 u32 code_offset, checkpos;
    1455          28 :                 ft->has_layout = swf_read_int(read, 1);
    1456          28 :                 ft->has_shiftJIS = swf_read_int(read, 1);
    1457          28 :                 ft->is_unicode = swf_read_int(read, 1);
    1458          28 :                 ft->is_ansi = swf_read_int(read, 1);
    1459          14 :                 wide_offset = swf_read_int(read, 1);
    1460          14 :                 wide_codes = swf_read_int(read, 1);
    1461          28 :                 ft->is_italic = swf_read_int(read, 1);
    1462          28 :                 ft->is_bold = swf_read_int(read, 1);
    1463          14 :                 swf_read_int(read, 8);
    1464          14 :                 count = swf_read_int(read, 8);
    1465          14 :                 ft->fontName = (char*)gf_malloc(sizeof(u8)*count+1);
    1466          14 :                 ft->fontName[count] = 0;
    1467          84 :                 for (i=0; i<count; i++) ft->fontName[i] = swf_read_int(read, 8);
    1468             : 
    1469          14 :                 ft->nbGlyphs = swf_get_16(read);
    1470          14 :                 start = swf_get_file_pos(read);
    1471             : 
    1472          14 :                 if (ft->nbGlyphs) {
    1473           8 :                         offset_table = (u32*)gf_malloc(sizeof(u32) * ft->nbGlyphs);
    1474         130 :                         for (i=0; i<ft->nbGlyphs; i++) {
    1475         122 :                                 if (wide_offset) offset_table[i] = swf_get_32(read);
    1476         122 :                                 else offset_table[i] = swf_get_16(read);
    1477             :                         }
    1478             :                 }
    1479             : 
    1480          14 :                 if (wide_offset) {
    1481           0 :                         code_offset = swf_get_32(read);
    1482             :                 } else {
    1483          14 :                         code_offset = swf_get_16(read);
    1484             :                 }
    1485             : 
    1486          14 :                 if (ft->nbGlyphs) {
    1487         122 :                         for (i=0; i<ft->nbGlyphs; i++) {
    1488         122 :                                 swf_align(read);
    1489         122 :                                 e = swf_seek_file_to(read, start + offset_table[i]);
    1490         122 :                                 if (e) break;
    1491             : 
    1492         122 :                                 swf_parse_shape_def(read, ft, 0);
    1493             :                         }
    1494           8 :                         gf_free(offset_table);
    1495           8 :                         if (e) return e;
    1496             : 
    1497           8 :                         checkpos = swf_get_file_pos(read);
    1498           8 :                         if (checkpos != start + code_offset) {
    1499           0 :                                 GF_LOG(GF_LOG_ERROR, GF_LOG_PARSER, ("[SWF Parsing] bad code offset in font\n"));
    1500             :                                 return GF_NON_COMPLIANT_BITSTREAM;
    1501             :                         }
    1502             : 
    1503           8 :                         ft->glyph_codes = (u16*)gf_malloc(sizeof(u16) * ft->nbGlyphs);
    1504         130 :                         for (i=0; i<ft->nbGlyphs; i++) {
    1505         204 :                                 if (wide_codes) ft->glyph_codes[i] = swf_get_16(read);
    1506          80 :                                 else ft->glyph_codes[i] = swf_read_int(read, 8);
    1507             :                         }
    1508             :                 }
    1509          14 :                 if (ft->has_layout) {
    1510          10 :                         ft->ascent = swf_get_s16(read);
    1511          10 :                         ft->descent = swf_get_s16(read);
    1512          10 :                         ft->leading = swf_get_s16(read);
    1513          10 :                         if (ft->nbGlyphs) {
    1514           8 :                                 ft->glyph_adv = (s16*)gf_malloc(sizeof(s16) * ft->nbGlyphs);
    1515           8 :                                 for (i=0; i<ft->nbGlyphs; i++) ft->glyph_adv[i] = swf_get_s16(read);
    1516         122 :                                 for (i=0; i<ft->nbGlyphs; i++) swf_get_rec(read, &rc);
    1517             :                         }
    1518             :                         /*kerning info*/
    1519          10 :                         count = swf_get_16(read);
    1520          10 :                         for (i=0; i<count; i++) {
    1521           0 :                                 if (wide_codes) {
    1522             :                                         swf_get_16(read);
    1523             :                                         swf_get_16(read);
    1524             :                                 } else {
    1525           0 :                                         swf_read_int(read, 8);
    1526           0 :                                         swf_read_int(read, 8);
    1527             :                                 }
    1528           0 :                                 swf_get_s16(read);
    1529             :                         }
    1530             :                 }
    1531             :         }
    1532             : 
    1533          25 :         gf_list_add(read->fonts, ft);
    1534          25 :         return GF_OK;
    1535             : }
    1536             : 
    1537          11 : static GF_Err swf_def_font_info(SWFReader *read)
    1538             : {
    1539             :         SWFFont *ft;
    1540             :         Bool wide_chars;
    1541             :         u32 i, count;
    1542             : 
    1543          11 :         i = swf_get_16(read);
    1544          11 :         ft = swf_find_font(read, i);
    1545          11 :         if (!ft) {
    1546           0 :                 swf_report(read, GF_BAD_PARAM, "Cannot locate font ID %d", i);
    1547           0 :                 return GF_BAD_PARAM;
    1548             :         }
    1549             :         /*overwrite font info*/
    1550          11 :         if (ft->fontName) gf_free(ft->fontName);
    1551          11 :         count = swf_read_int(read, 8);
    1552          11 :         ft->fontName = (char*)gf_malloc(sizeof(char) * (count+1));
    1553          11 :         ft->fontName[count] = 0;
    1554         158 :         for (i=0; i<count; i++) ft->fontName[i] = swf_read_int(read, 8);
    1555          11 :         swf_read_int(read, 2);
    1556          22 :         ft->is_unicode = swf_read_int(read, 1);
    1557          22 :         ft->has_shiftJIS = swf_read_int(read, 1);
    1558          22 :         ft->is_ansi = swf_read_int(read, 1);
    1559          22 :         ft->is_italic = swf_read_int(read, 1);
    1560          22 :         ft->is_bold = swf_read_int(read, 1);
    1561             :         /*TODO - this should be remapped to a font data stream, we currently only assume the glyph code
    1562             :         table is the same as the original font file...*/
    1563          11 :         wide_chars = swf_read_int(read, 1);
    1564          11 :         if (ft->glyph_codes) gf_free(ft->glyph_codes);
    1565          11 :         ft->glyph_codes = (u16*)gf_malloc(sizeof(u16) * ft->nbGlyphs);
    1566             : 
    1567         296 :         for (i=0; i<ft->nbGlyphs; i++) {
    1568         285 :                 if (wide_chars) ft->glyph_codes[i] = swf_get_16(read);
    1569         570 :                 else ft->glyph_codes[i] = swf_read_int(read, 8);
    1570             :         }
    1571             :         return GF_OK;
    1572             : }
    1573             : 
    1574          81 : static GF_Err swf_def_text(SWFReader *read, u32 revision)
    1575             : {
    1576             :         SWFRec rc;
    1577             :         SWFText txt;
    1578             :         Bool flag;
    1579             :         u32 nbits_adv, nbits_glyph, i, col, fontID, count, font_height;
    1580             :         Fixed offX, offY;
    1581             :         GF_Err e;
    1582             : 
    1583          81 :         txt.ID = swf_get_16(read);
    1584          81 :         swf_get_rec(read, &rc);
    1585          81 :         swf_get_matrix(read, &txt.mat);
    1586          81 :         txt.text = gf_list_new();
    1587             : 
    1588          81 :         swf_align(read);
    1589          81 :         nbits_glyph = swf_read_int(read, 8);
    1590          81 :         nbits_adv = swf_read_int(read, 8);
    1591             :         fontID = 0;
    1592             :         offX = offY = 0;
    1593             :         font_height = 0;
    1594             :         col = 0xFF000000;
    1595             :         e = GF_OK;
    1596             : 
    1597             :         while (1) {
    1598         273 :                 flag = swf_read_int(read, 1);
    1599             :                 /*regular glyph record*/
    1600         273 :                 if (!flag) {
    1601             :                         SWFGlyphRec *gr;
    1602         177 :                         count = swf_read_int(read, 7);
    1603         177 :                         if (!count) break;
    1604             : 
    1605          96 :                         if (!fontID) {
    1606             :                                 e = GF_BAD_PARAM;
    1607           0 :                                 swf_report(read, GF_BAD_PARAM, "Defining text %d without assigning font", fontID);
    1608             :                                 break;
    1609             :                         }
    1610             : 
    1611          96 :                         GF_SAFEALLOC(gr, SWFGlyphRec);
    1612          96 :                         if (!gr) return GF_OUT_OF_MEM;
    1613             : 
    1614          96 :                         gf_list_add(txt.text, gr);
    1615          96 :                         gr->fontID = fontID;
    1616          96 :                         gr->fontSize = font_height;
    1617          96 :                         gr->col = col;
    1618          96 :                         gr->orig_x = offX;
    1619          96 :                         gr->orig_y = offY;
    1620          96 :                         gr->nbGlyphs = count;
    1621          96 :                         gr->indexes = (u32*)gf_malloc(sizeof(u32) * gr->nbGlyphs);
    1622          96 :                         gr->dx = (Fixed*)gf_malloc(sizeof(Fixed) * gr->nbGlyphs);
    1623        1857 :                         for (i=0; i<gr->nbGlyphs; i++) {
    1624        3522 :                                 gr->indexes[i] = swf_read_int(read, nbits_glyph);
    1625        3522 :                                 gr->dx[i] = FLT2FIX( swf_read_int(read, nbits_adv) * SWF_TWIP_SCALE );
    1626             :                         }
    1627          96 :                         swf_align(read);
    1628             :                 }
    1629             :                 /*text state change*/
    1630             :                 else {
    1631             :                         Bool has_font, has_col, has_y_off, has_x_off;
    1632             :                         /*reserved*/
    1633          96 :                         swf_read_int(read, 3);
    1634          96 :                         has_font = swf_read_int(read, 1);
    1635          96 :                         has_col = swf_read_int(read, 1);
    1636          96 :                         has_y_off = swf_read_int(read, 1);
    1637          96 :                         has_x_off = swf_read_int(read, 1);
    1638             : 
    1639             :                         /*end of rec*/
    1640          96 :                         if (!has_font && !has_col && !has_y_off && !has_x_off) break;
    1641         177 :                         if (has_font) fontID = swf_get_16(read);
    1642          96 :                         if (has_col) {
    1643          81 :                                 if (revision==0) col = swf_get_color(read);
    1644           0 :                                 else col = swf_get_argb(read);
    1645             :                         }
    1646             :                         /*openSWF spec seems to have wrong order here*/
    1647          96 :                         if (has_x_off) offX = FLT2FIX( swf_get_s16(read) * SWF_TWIP_SCALE );
    1648          96 :                         if (has_y_off) offY = FLT2FIX( swf_get_s16(read) * SWF_TWIP_SCALE );
    1649         177 :                         if (has_font) font_height = swf_get_16(read);
    1650             :                 }
    1651             :         }
    1652             : 
    1653             :         if (e) goto exit;
    1654             : 
    1655          81 :         if (! (read->flags & GF_SM_SWF_NO_TEXT) ) {
    1656          81 :                 e = read->define_text(read, &txt);
    1657             :         }
    1658             : 
    1659           0 : exit:
    1660         177 :         while (gf_list_count(txt.text)) {
    1661          96 :                 SWFGlyphRec *gr = (SWFGlyphRec *)gf_list_get(txt.text, 0);
    1662          96 :                 gf_list_rem(txt.text, 0);
    1663          96 :                 if (gr->indexes) gf_free(gr->indexes);
    1664          96 :                 if (gr->dx) gf_free(gr->dx);
    1665          96 :                 gf_free(gr);
    1666             :         }
    1667          81 :         gf_list_del(txt.text);
    1668             : 
    1669          81 :         return e;
    1670             : }
    1671             : 
    1672             : 
    1673           4 : static GF_Err swf_def_edit_text(SWFReader *read)
    1674             : {
    1675             :         GF_Err e;
    1676             :         SWFEditText txt;
    1677             :         char *var_name;
    1678             :         Bool has_text, has_text_color, has_max_length, has_font;
    1679             : 
    1680             :         memset(&txt, 0, sizeof(SWFEditText));
    1681           4 :         txt.color = 0xFF000000;
    1682             : 
    1683           4 :         txt.ID = swf_get_16(read);
    1684           4 :         swf_get_rec(read, &txt.bounds);
    1685           4 :         swf_align(read);
    1686             : 
    1687           4 :         has_text = swf_read_int(read, 1);
    1688           8 :         txt.word_wrap = swf_read_int(read, 1);
    1689           8 :         txt.multiline = swf_read_int(read, 1);
    1690           8 :         txt.password = swf_read_int(read, 1);
    1691           8 :         txt.read_only = swf_read_int(read, 1);
    1692           4 :         has_text_color = swf_read_int(read, 1);
    1693           4 :         has_max_length = swf_read_int(read, 1);
    1694           4 :         has_font = swf_read_int(read, 1);
    1695           4 :         /*reserved*/swf_read_int(read, 1);
    1696           8 :         txt.auto_size = swf_read_int(read, 1);
    1697           8 :         txt.has_layout = swf_read_int(read, 1);
    1698           8 :         txt.no_select = swf_read_int(read, 1);
    1699           8 :         txt.border = swf_read_int(read, 1);
    1700           4 :         /*reserved*/swf_read_int(read, 1);
    1701           8 :         txt.html = swf_read_int(read, 1);
    1702           8 :         txt.outlines = swf_read_int(read, 1);
    1703             : 
    1704           4 :         if (has_font) {
    1705           4 :                 txt.fontID = swf_get_16(read);
    1706           4 :                 txt.font_height = FLT2FIX( swf_get_16(read) * SWF_TWIP_SCALE );
    1707             :         }
    1708           4 :         if (has_text_color) txt.color = swf_get_argb(read);
    1709           4 :         if (has_max_length) txt.max_length = FLT2FIX( swf_get_16(read) * SWF_TWIP_SCALE );
    1710             : 
    1711           4 :         if (txt.has_layout) {
    1712           4 :                 txt.align = swf_read_int(read, 8);
    1713           2 :                 txt.left = FLT2FIX( swf_get_16(read) * SWF_TWIP_SCALE );
    1714           2 :                 txt.right = FLT2FIX( swf_get_16(read) * SWF_TWIP_SCALE );
    1715           2 :                 txt.indent = FLT2FIX( swf_get_16(read) * SWF_TWIP_SCALE );
    1716           2 :                 txt.leading = FLT2FIX( swf_get_16(read) * SWF_TWIP_SCALE );
    1717             :         }
    1718           4 :         var_name = swf_get_string(read);
    1719           4 :         if (has_text) txt.init_value = swf_get_string(read);
    1720             : 
    1721             :         e = GF_OK;
    1722           4 :         if (! (read->flags & GF_SM_SWF_NO_TEXT) ) {
    1723           4 :                 e = read->define_edit_text(read, &txt);
    1724             :         }
    1725           4 :         gf_free(var_name);
    1726           4 :         if (txt.init_value) gf_free(txt.init_value);
    1727             : 
    1728           4 :         return e;
    1729             : }
    1730             : 
    1731          31 : static void swf_delete_sound_stream(SWFReader *read)
    1732             : {
    1733          31 :         if (!read->sound_stream) return;
    1734           2 :         if (read->sound_stream->output) gf_fclose(read->sound_stream->output);
    1735           2 :         if (read->sound_stream->szFileName) gf_free(read->sound_stream->szFileName);
    1736           2 :         gf_free(read->sound_stream);
    1737           2 :         read->sound_stream = NULL;
    1738             : }
    1739             : 
    1740          18 : static GF_Err swf_def_sprite(SWFReader *read)
    1741             : {
    1742             :         GF_Err e;
    1743             :         GF_List *prev_dlist;
    1744             :         u32 frame_count;
    1745             :         Bool prev_sprite;
    1746             :         u32 prev_frame, prev_depth;
    1747             :         SWFSound *snd;
    1748             : 
    1749          18 :         prev_sprite = read->current_sprite_id;
    1750          18 :         read->current_sprite_id = swf_get_16(read);
    1751          18 :         frame_count = swf_get_16(read);
    1752             : 
    1753             :         /*store frame state*/
    1754          18 :         prev_frame = read->current_frame;
    1755          18 :         read->current_frame = 0;
    1756             :         /*store soundStream state*/
    1757          18 :         snd = read->sound_stream;
    1758          18 :         read->sound_stream = NULL;
    1759             :         /*store depth state*/
    1760          18 :         prev_depth = read->max_depth;
    1761          18 :         read->max_depth = 0;
    1762             : 
    1763          18 :         prev_dlist = read->display_list;
    1764          18 :         read->display_list = gf_list_new();
    1765             : 
    1766          18 :         e = read->define_sprite(read, frame_count);
    1767          18 :         if (e) return e;
    1768             : 
    1769             :         /*close sprite soundStream*/
    1770          18 :         swf_delete_sound_stream(read);
    1771             :         /*restore sound stream*/
    1772          18 :         read->sound_stream = snd;
    1773          18 :         read->max_depth = prev_depth;
    1774             : 
    1775          51 :         while (gf_list_count(read->display_list)) {
    1776          15 :                 DispShape *s = (DispShape *)gf_list_get(read->display_list, 0);
    1777          15 :                 gf_list_rem(read->display_list, 0);
    1778          15 :                 gf_free(s);
    1779             :         }
    1780          18 :         gf_list_del(read->display_list);
    1781          18 :         read->display_list = prev_dlist;
    1782             : 
    1783          18 :         read->current_frame = prev_frame;
    1784          18 :         read->current_sprite_id = prev_sprite;
    1785             : 
    1786          18 :         read->tag = SWF_DEFINESPRITE;
    1787          18 :         return GF_OK;
    1788             : }
    1789             : 
    1790           2 : static GF_Err swf_def_sound(SWFReader *read)
    1791             : {
    1792             :         SWFSound *snd;
    1793           2 :         GF_SAFEALLOC(snd , SWFSound);
    1794           2 :         if (!snd) return GF_OUT_OF_MEM;
    1795           2 :         snd->ID = swf_get_16(read);
    1796           4 :         snd->format = swf_read_int(read, 4);
    1797           4 :         snd->sound_rate = swf_read_int(read, 2);
    1798           4 :         snd->bits_per_sample = swf_read_int(read, 1) ? 16 : 8;
    1799           4 :         snd->stereo = swf_read_int(read, 1);
    1800           2 :         snd->sample_count = swf_get_32(read);
    1801             : 
    1802           2 :         switch (snd->format) {
    1803             :         /*raw PCM*/
    1804           0 :         case 0:
    1805           0 :                 swf_report(read, GF_NOT_SUPPORTED, "Raw PCM Audio not supported");
    1806           0 :                 gf_free(snd);
    1807           0 :                 break;
    1808             :         /*ADPCM*/
    1809           0 :         case 1:
    1810           0 :                 swf_report(read, GF_NOT_SUPPORTED, "AD-PCM Audio not supported");
    1811           0 :                 gf_free(snd);
    1812           0 :                 break;
    1813             :         /*MP3*/
    1814           2 :         case 2:
    1815             :         {
    1816             :                 char szName[1024];
    1817             :                 u32 alloc_size, tot_size;
    1818             :                 char *frame;
    1819             : 
    1820           2 :                 sprintf(szName, "swf_sound_%d.mp3", snd->ID);
    1821           2 :                 if (read->localPath) {
    1822           2 :                         snd->szFileName = (char*)gf_malloc(sizeof(char)*GF_MAX_PATH);
    1823           2 :                         strcpy(snd->szFileName, read->localPath);
    1824           2 :                         strcat(snd->szFileName, szName);
    1825             :                 } else {
    1826           0 :                         snd->szFileName = gf_strdup(szName);
    1827             :                 }
    1828           2 :                 snd->output = gf_fopen(snd->szFileName, "wb");
    1829             : 
    1830             :                 alloc_size = 4096;
    1831           2 :                 frame = (char*)gf_malloc(sizeof(char)*4096);
    1832             :                 /*snd->frame_delay_ms =*/ swf_get_16(read);
    1833           2 :                 snd->frame_delay_ms = read->current_frame*1000;
    1834           2 :                 snd->frame_delay_ms /= read->frame_rate;
    1835             :                 tot_size = 9;
    1836             :                 /*parse all frames*/
    1837          96 :                 while (tot_size<read->size) {
    1838          92 :                         u32 toread = read->size - tot_size;
    1839          92 :                         if (toread>alloc_size) toread = alloc_size;
    1840          92 :                         swf_read_data(read, frame, toread);
    1841          92 :                         gf_fwrite(frame, sizeof(char)*toread, snd->output);
    1842          92 :                         tot_size += toread;
    1843             :                 }
    1844             : 
    1845           2 :                 gf_free(frame);
    1846           2 :                 return gf_list_add(read->sounds, snd);
    1847             :         }
    1848           0 :         case 3:
    1849           0 :                 swf_report(read, GF_NOT_SUPPORTED, "Unrecognized sound format");
    1850           0 :                 gf_free(snd);
    1851           0 :                 break;
    1852             :         }
    1853             :         return GF_OK;
    1854             : }
    1855             : 
    1856             : 
    1857             : typedef struct
    1858             : {
    1859             :         u32 sync_flags;
    1860             :         u32 in_point, out_point;
    1861             :         u32 nb_loops;
    1862             : } SoundInfo;
    1863             : 
    1864           2 : static SoundInfo swf_skip_soundinfo(SWFReader *read)
    1865             : {
    1866             :         SoundInfo si;
    1867           2 :         u32 sync_flags = swf_read_int(read, 4);
    1868           2 :         Bool has_env = swf_read_int(read, 1);
    1869           2 :         Bool has_loops = swf_read_int(read, 1);
    1870           2 :         Bool has_out_pt = swf_read_int(read, 1);
    1871           2 :         Bool has_in_pt = swf_read_int(read, 1);
    1872             : 
    1873             :         memset(&si, 0, sizeof(SoundInfo));
    1874           2 :         si.sync_flags = sync_flags;
    1875           2 :         if (has_in_pt) si.in_point = swf_get_32(read);
    1876           2 :         if (has_out_pt) si.out_point = swf_get_32(read);
    1877           2 :         if (has_loops) si.nb_loops = swf_get_16(read);
    1878             :         /*we ignore the envelope*/
    1879           2 :         if (has_env) {
    1880             :                 u32 i;
    1881           0 :                 u32 nb_ctrl = swf_read_int(read, 8);
    1882           0 :                 for (i=0; i<nb_ctrl; i++) {
    1883           0 :                         swf_read_int(read, 32); /*mark44*/
    1884           0 :                         swf_read_int(read, 16); /*l0*/
    1885           0 :                         swf_read_int(read, 16); /*l1*/
    1886             :                 }
    1887             :         }
    1888           2 :         return si;
    1889             : }
    1890             : 
    1891             : static SWFSound *sndswf_get_sound(SWFReader *read, u32 ID)
    1892             : {
    1893             :         u32 i;
    1894             :         SWFSound *snd;
    1895           2 :         i=0;
    1896           2 :         while ((snd = (SWFSound *)gf_list_enum(read->sounds, &i))) {
    1897           2 :                 if (snd->ID==ID) return snd;
    1898             :         }
    1899             :         return NULL;
    1900             : }
    1901             : 
    1902           2 : static GF_Err swf_start_sound(SWFReader *read)
    1903             : {
    1904             :         SWFSound *snd;
    1905           2 :         u32 ID = swf_get_16(read);
    1906             :         SoundInfo si;
    1907           2 :         si = swf_skip_soundinfo(read);
    1908             : 
    1909             :         snd = sndswf_get_sound(read, ID);
    1910           2 :         if (!snd) {
    1911           0 :                 swf_report(read, GF_BAD_PARAM, "Cannot find sound with ID %d", ID);
    1912           0 :                 return GF_OK;
    1913             :         }
    1914           2 :         if (!snd->is_setup) {
    1915           2 :                 GF_Err e = read->setup_sound(read, snd, 0);
    1916           2 :                 if (e) return e;
    1917           2 :                 snd->is_setup = 1;
    1918             :         }
    1919           2 :         return read->start_sound(read, snd, (si.sync_flags & 0x2) ? 1 : 0);
    1920             : }
    1921             : 
    1922           2 : static GF_Err swf_soundstream_hdr(SWFReader *read)
    1923             : {
    1924             :         char szName[1024];
    1925             :         SWFSound *snd;
    1926             : 
    1927           2 :         if (read->sound_stream) {
    1928           0 :                 swf_report(read, GF_BAD_PARAM, "More than one sound stream for current timeline!!");
    1929           0 :                 return swf_func_skip(read);
    1930             :         }
    1931             : 
    1932           2 :         GF_SAFEALLOC(snd, SWFSound);
    1933           2 :         if (!snd) return GF_OUT_OF_MEM;
    1934             : 
    1935           2 :         /*rec_mix = */swf_read_int(read, 8);
    1936             :         /*0: uncompressed, 1: ADPCM, 2: MP3*/
    1937           4 :         snd->format = swf_read_int(read, 4);
    1938             :         /*0: 5.5k, 1: 11k, 2: 2: 22k, 3: 44k*/
    1939           4 :         snd->sound_rate = swf_read_int(read, 2);
    1940             :         /*0: 8 bit, 1: 16 bit*/
    1941           4 :         snd->bits_per_sample = swf_read_int(read, 1) ? 16 : 8;
    1942             :         /*0: mono, 8 1: stereo*/
    1943           4 :         snd->stereo = swf_read_int(read, 1);
    1944             :         /*samplesperframe hint*/
    1945           2 :         swf_read_int(read, 16);
    1946             : 
    1947           2 :         switch (snd->format) {
    1948             :         /*raw PCM*/
    1949           0 :         case 0:
    1950           0 :                 swf_report(read, GF_NOT_SUPPORTED, "Raw PCM Audio not supported");
    1951           0 :                 gf_free(snd);
    1952           0 :                 break;
    1953             :         /*ADPCM*/
    1954           0 :         case 1:
    1955           0 :                 swf_report(read, GF_NOT_SUPPORTED, "AD-PCM Audio not supported");
    1956           0 :                 gf_free(snd);
    1957           0 :                 break;
    1958             :         /*MP3*/
    1959           2 :         case 2:
    1960           2 :                 read->sound_stream = snd;
    1961           2 :                 if (read->localPath) {
    1962           2 :                         sprintf(szName, "%s/swf_soundstream_%d.mp3", read->localPath, read->current_sprite_id);
    1963             :                 } else {
    1964           0 :                         sprintf(szName, "swf_soundstream_%d.mp3", read->current_sprite_id);
    1965             :                 }
    1966           2 :                 read->sound_stream->szFileName = gf_strdup(szName);
    1967           2 :                 read->setup_sound(read, read->sound_stream, 0);
    1968           2 :                 break;
    1969           0 :         case 3:
    1970           0 :                 swf_report(read, GF_NOT_SUPPORTED, "Unrecognized sound format");
    1971           0 :                 gf_free(snd);
    1972           0 :                 break;
    1973             :         }
    1974             :         return GF_OK;
    1975             : }
    1976             : 
    1977         336 : static GF_Err swf_soundstream_block(SWFReader *read)
    1978             : {
    1979             : #ifdef GPAC_DISABLE_AV_PARSERS
    1980             :         return swf_func_skip(read);
    1981             : #else
    1982             :         unsigned char bytes[4];
    1983             :         u32 hdr, alloc_size, size, tot_size, samplesPerFrame;
    1984             :         char *frame;
    1985             : 
    1986             :         /*note we're doing only MP3*/
    1987         336 :         if (!read->sound_stream) return swf_func_skip(read);
    1988             : 
    1989             :         samplesPerFrame = swf_get_16(read);
    1990             :         /*delay = */swf_get_16(read);
    1991             : 
    1992         336 :         if (!read->sound_stream->is_setup) {
    1993             : 
    1994             :                 /*error at setup*/
    1995           2 :                 if (!read->sound_stream->output) {
    1996           2 :                         read->sound_stream->output = gf_fopen(read->sound_stream->szFileName, "wb");
    1997           2 :                         if (!read->sound_stream->output)
    1998           0 :                                 return swf_func_skip(read);
    1999             :                 }
    2000             :                 /*store TS of first AU*/
    2001           2 :                 read->sound_stream->frame_delay_ms = read->current_frame*1000;
    2002           2 :                 read->sound_stream->frame_delay_ms /= read->frame_rate;
    2003           2 :                 read->setup_sound(read, read->sound_stream, 1);
    2004           2 :                 read->sound_stream->is_setup = 1;
    2005             :         }
    2006             : 
    2007         336 :         if (!samplesPerFrame) return GF_OK;
    2008             : 
    2009             :         alloc_size = 1;
    2010         334 :         frame = (char*)gf_malloc(sizeof(char));
    2011             :         tot_size = 4;
    2012             :         /*parse all frames*/
    2013             :         while (1) {
    2014        1072 :                 bytes[0] = swf_read_int(read, 8);
    2015        1072 :                 bytes[1] = swf_read_int(read, 8);
    2016        1072 :                 bytes[2] = swf_read_int(read, 8);
    2017        1072 :                 bytes[3] = swf_read_int(read, 8);
    2018         536 :                 hdr = GF_4CC(bytes[0], bytes[1], bytes[2], bytes[3]);
    2019         536 :                 size = gf_mp3_frame_size(hdr);
    2020         536 :                 if (alloc_size<size-4) {
    2021         334 :                         frame = (char*)gf_realloc(frame, sizeof(char)*(size-4));
    2022             :                         alloc_size = size-4;
    2023             :                 }
    2024             :                 /*watchout for truncated framesif */
    2025         536 :                 if (tot_size + size >= read->size) size = read->size - tot_size;
    2026             : 
    2027         536 :                 swf_read_data(read, frame, size-4);
    2028         536 :                 gf_fwrite(bytes, sizeof(char)*4, read->sound_stream->output);
    2029         536 :                 gf_fwrite(frame, sizeof(char)*(size-4), read->sound_stream->output);
    2030         536 :                 if (tot_size + size >= read->size) break;
    2031             :                 tot_size += size;
    2032             :         }
    2033         334 :         gf_free(frame);
    2034         334 :         return GF_OK;
    2035             : #endif
    2036             : }
    2037             : 
    2038           0 : static GF_Err swf_def_hdr_jpeg(SWFReader *read)
    2039             : {
    2040           0 :         if (!read) return GF_OK;
    2041           0 :         if (read->jpeg_hdr) {
    2042           0 :                 swf_report(read, GF_NON_COMPLIANT_BITSTREAM, "JPEG Table already defined in file");
    2043           0 :                 return GF_NON_COMPLIANT_BITSTREAM;
    2044             :         }
    2045           0 :         read->jpeg_hdr_size = read->size;
    2046           0 :         if (read->size) {
    2047           0 :                 read->jpeg_hdr = gf_malloc(sizeof(char)*read->size);
    2048           0 :                 swf_read_data(read, (char *) read->jpeg_hdr, read->size);
    2049             :         }
    2050             :         return GF_OK;
    2051             : }
    2052             : 
    2053             : 
    2054           2 : static GF_Err swf_def_bits_jpeg(SWFReader *read, u32 version)
    2055             : {
    2056             :         u32 ID;
    2057             :         FILE *file = NULL;
    2058             :         char szName[1024];
    2059             :         u8 *buf;
    2060             :         u32 skip = 0;
    2061             : #ifndef GPAC_DISABLE_AV_PARSERS
    2062             :         u32 AlphaPlaneSize = 0;
    2063             : #endif
    2064           2 :         u32 size = read->size;
    2065             : 
    2066           2 :         ID = swf_get_16(read);
    2067           2 :         size -= 2;
    2068           2 :         if (version==3) {
    2069           0 :                 u32 offset = swf_get_32(read);
    2070             : #ifndef GPAC_DISABLE_AV_PARSERS
    2071           0 :                 size -= 4;
    2072           0 :                 AlphaPlaneSize = size - offset;
    2073             : #endif
    2074             :                 size = offset;
    2075             :         }
    2076             : 
    2077             :         /*dump file*/
    2078           2 :         if (read->localPath) {
    2079             :                 sprintf(szName, "%s/swf_jpeg_%d.jpg", read->localPath, ID);
    2080             :         } else {
    2081             :                 sprintf(szName, "swf_jpeg_%d.jpg", ID);
    2082             :         }
    2083             : 
    2084           2 :         if (version!=3)
    2085           2 :                 file = gf_fopen(szName, "wb");
    2086             : 
    2087           2 :         if (version==1 && read->jpeg_hdr_size) {
    2088             :                 /*remove JPEG EOI*/
    2089           0 :                 gf_fwrite(read->jpeg_hdr, read->jpeg_hdr_size-2, file);
    2090             :                 /*remove JPEG SOI*/
    2091             :                 swf_get_16(read);
    2092           0 :                 size-=2;
    2093             :         }
    2094           2 :         buf = gf_malloc(sizeof(u8)*size);
    2095           2 :         swf_read_data(read, (char *) buf, size);
    2096           2 :         if (version==1) {
    2097           0 :                 gf_fwrite(buf, size, file);
    2098             :         } else {
    2099             :                 u32 i;
    2100       12648 :                 for (i=0; i<size; i++) {
    2101       12648 :                         if ((i+4<size)
    2102       12640 :                                 && (buf[i]==0xFF) && (buf[i+1]==0xD9)
    2103           0 :                                 && (buf[i+2]==0xFF) && (buf[i+3]==0xD8)
    2104             :                            ) {
    2105           0 :                                 memmove(buf+i, buf+i+4, sizeof(char)*(size-i-4));
    2106           0 :                                 size -= 4;
    2107           0 :                                 break;
    2108             :                         }
    2109             :                 }
    2110           2 :                 if ((buf[0]==0xFF) && (buf[1]==0xD8) && (buf[2]==0xFF) && (buf[3]==0xD8)) {
    2111             :                         skip = 2;
    2112             :                 }
    2113           2 :                 if (version==2)
    2114           2 :                         gf_fwrite(buf+skip, size-skip, file);
    2115             :         }
    2116           2 :         if (version!=3)
    2117           2 :                 gf_fclose(file);
    2118             : 
    2119           2 :         if (version==3) {
    2120             : #ifndef GPAC_DISABLE_AV_PARSERS
    2121             :                 char *dst, *raw;
    2122             :                 GF_Err e;
    2123             :                 u32 codecid;
    2124             :                 u32 osize, w, h, j, pf;
    2125             :                 GF_BitStream *bs;
    2126             : 
    2127             :                 /*decompress jpeg*/
    2128           0 :                 bs = gf_bs_new( (char *) buf+skip, size-skip, GF_BITSTREAM_READ);
    2129           0 :                 gf_img_parse(bs, &codecid, &w, &h, NULL, NULL);
    2130           0 :                 gf_bs_del(bs);
    2131             : 
    2132           0 :                 osize = w*h*4;
    2133           0 :                 raw = gf_malloc(sizeof(char)*osize);
    2134           0 :                 memset(raw, 0, sizeof(char)*osize);
    2135           0 :                 e = gf_img_jpeg_dec(buf+skip, size-skip, &w, &h, &pf, raw, &osize, 4);
    2136           0 :                 if (e != GF_OK) {
    2137           0 :                         swf_report(read, e, "Cannopt decode JPEG image");
    2138             :                 }
    2139             : 
    2140             :                 /*read alpha map and decompress it*/
    2141           0 :                 if (size<AlphaPlaneSize) buf = gf_realloc(buf, sizeof(u8)*AlphaPlaneSize);
    2142           0 :                 swf_read_data(read, (char *) buf, AlphaPlaneSize);
    2143             : 
    2144           0 :                 osize = w*h;
    2145           0 :                 dst = gf_malloc(sizeof(char)*osize);
    2146           0 :                 uncompress((Bytef *) dst, (uLongf *) &osize, buf, AlphaPlaneSize);
    2147             :                 /*write alpha channel*/
    2148           0 :                 for (j=0; j<osize; j++) {
    2149           0 :                         raw[4*j + 3] = dst[j];
    2150             :                 }
    2151           0 :                 gf_free(dst);
    2152             : 
    2153             :                 /*write png*/
    2154           0 :                 if (read->localPath) {
    2155             :                         sprintf(szName, "%s/swf_png_%d.png", read->localPath, ID);
    2156             :                 } else {
    2157             :                         sprintf(szName, "swf_png_%d.png", ID);
    2158             :                 }
    2159             : 
    2160           0 :                 osize = w*h*4;
    2161           0 :                 buf = gf_realloc(buf, sizeof(char)*osize);
    2162           0 :                 gf_img_png_enc(raw, w, h, h*4, GF_PIXEL_RGBA, (char *)buf, &osize);
    2163             : 
    2164           0 :                 file = gf_fopen(szName, "wb");
    2165           0 :                 gf_fwrite(buf, osize, file);
    2166           0 :                 gf_fclose(file);
    2167             : 
    2168           0 :                 gf_free(raw);
    2169             : #endif //GPAC_DISABLE_AV_PARSERS
    2170             :         }
    2171           2 :         gf_free(buf);
    2172             : 
    2173           2 :         return read->setup_image(read, ID, szName);
    2174             : }
    2175             : 
    2176             : 
    2177           0 : static const char *swf_get_tag_name(u32 tag)
    2178             : {
    2179           0 :         switch (tag) {
    2180             :         case SWF_END:
    2181             :                 return "End";
    2182           0 :         case SWF_SHOWFRAME:
    2183           0 :                 return "ShowFrame";
    2184           0 :         case SWF_DEFINESHAPE:
    2185           0 :                 return "DefineShape";
    2186           0 :         case SWF_FREECHARACTER:
    2187           0 :                 return "FreeCharacter";
    2188           0 :         case SWF_PLACEOBJECT:
    2189           0 :                 return "PlaceObject";
    2190           0 :         case SWF_REMOVEOBJECT:
    2191           0 :                 return "RemoveObject";
    2192           0 :         case SWF_DEFINEBITSJPEG:
    2193           0 :                 return "DefineBitsJPEG";
    2194           0 :         case SWF_DEFINEBUTTON:
    2195           0 :                 return "DefineButton";
    2196           0 :         case SWF_JPEGTABLES:
    2197           0 :                 return "JPEGTables";
    2198           0 :         case SWF_SETBACKGROUNDCOLOR:
    2199           0 :                 return "SetBackgroundColor";
    2200           0 :         case SWF_DEFINEFONT:
    2201           0 :                 return "DefineFont";
    2202           0 :         case SWF_DEFINETEXT:
    2203           0 :                 return "DefineText";
    2204           0 :         case SWF_DOACTION:
    2205           0 :                 return "DoAction";
    2206           0 :         case SWF_DEFINEFONTINFO:
    2207           0 :                 return "DefineFontInfo";
    2208           0 :         case SWF_DEFINESOUND:
    2209           0 :                 return "DefineSound";
    2210           0 :         case SWF_STARTSOUND:
    2211           0 :                 return "StartSound";
    2212           0 :         case SWF_DEFINEBUTTONSOUND:
    2213           0 :                 return "DefineButtonSound";
    2214           0 :         case SWF_SOUNDSTREAMHEAD:
    2215           0 :                 return "SoundStreamHead";
    2216           0 :         case SWF_SOUNDSTREAMBLOCK:
    2217           0 :                 return "SoundStreamBlock";
    2218           0 :         case SWF_DEFINEBITSLOSSLESS:
    2219           0 :                 return "DefineBitsLossless";
    2220           0 :         case SWF_DEFINEBITSJPEG2:
    2221           0 :                 return "DefineBitsJPEG2";
    2222           0 :         case SWF_DEFINESHAPE2:
    2223           0 :                 return "DefineShape2";
    2224           0 :         case SWF_DEFINEBUTTONCXFORM:
    2225           0 :                 return "DefineButtonCXForm";
    2226           0 :         case SWF_PROTECT:
    2227           0 :                 return "Protect";
    2228           0 :         case SWF_PLACEOBJECT2:
    2229           0 :                 return "PlaceObject2";
    2230           0 :         case SWF_REMOVEOBJECT2:
    2231           0 :                 return "RemoveObject2";
    2232           0 :         case SWF_DEFINESHAPE3:
    2233           0 :                 return "DefineShape3";
    2234           0 :         case SWF_DEFINETEXT2:
    2235           0 :                 return "DefineText2";
    2236           0 :         case SWF_DEFINEBUTTON2:
    2237           0 :                 return "DefineButton2";
    2238           0 :         case SWF_DEFINEBITSJPEG3:
    2239           0 :                 return "DefineBitsJPEG3";
    2240           0 :         case SWF_DEFINEBITSLOSSLESS2:
    2241           0 :                 return "DefineBitsLossless2";
    2242           0 :         case SWF_DEFINEEDITTEXT:
    2243           0 :                 return "DefineEditText";
    2244           0 :         case SWF_DEFINEMOVIE:
    2245           0 :                 return "DefineMovie";
    2246           0 :         case SWF_DEFINESPRITE:
    2247           0 :                 return "DefineSprite";
    2248           0 :         case SWF_NAMECHARACTER:
    2249           0 :                 return "NameCharacter";
    2250           0 :         case SWF_SERIALNUMBER:
    2251           0 :                 return "SerialNumber";
    2252           0 :         case SWF_GENERATORTEXT:
    2253           0 :                 return "GeneratorText";
    2254           0 :         case SWF_FRAMELABEL:
    2255           0 :                 return "FrameLabel";
    2256           0 :         case SWF_SOUNDSTREAMHEAD2:
    2257           0 :                 return "SoundStreamHead2";
    2258           0 :         case SWF_DEFINEMORPHSHAPE:
    2259           0 :                 return "DefineMorphShape";
    2260           0 :         case SWF_DEFINEFONT2:
    2261           0 :                 return "DefineFont2";
    2262           0 :         case SWF_TEMPLATECOMMAND:
    2263           0 :                 return "TemplateCommand";
    2264           0 :         case SWF_GENERATOR3:
    2265           0 :                 return "Generator3";
    2266           0 :         case SWF_EXTERNALFONT:
    2267           0 :                 return "ExternalFont";
    2268           0 :         case SWF_EXPORTASSETS:
    2269           0 :                 return "ExportAssets";
    2270           0 :         case SWF_IMPORTASSETS:
    2271           0 :                 return "ImportAssets";
    2272           0 :         case SWF_ENABLEDEBUGGER:
    2273           0 :                 return "EnableDebugger";
    2274           0 :         case SWF_MX0:
    2275           0 :                 return "MX0";
    2276           0 :         case SWF_MX1:
    2277           0 :                 return "MX1";
    2278           0 :         case SWF_MX2:
    2279           0 :                 return "MX2";
    2280           0 :         case SWF_MX3:
    2281           0 :                 return "MX3";
    2282           0 :         case SWF_MX4:
    2283           0 :                 return "MX4";
    2284           0 :         default:
    2285           0 :                 return "UnknownTag";
    2286             :         }
    2287             : }
    2288             : 
    2289           0 : static GF_Err swf_unknown_tag(SWFReader *read)
    2290             : {
    2291           0 :         if (!read) return GF_OK;
    2292           0 :         swf_report(read, GF_NOT_SUPPORTED, "Tag %s (0x%2x) not implemented - skipping", swf_get_tag_name(read->tag), read->tag);
    2293           0 :         return swf_func_skip(read);
    2294             : }
    2295             : 
    2296       10925 : static GF_Err swf_process_tag(SWFReader *read)
    2297             : {
    2298       10925 :         switch (read->tag) {
    2299             :         case SWF_END:
    2300             :                 return GF_OK;
    2301             :         case SWF_PROTECT:
    2302             :                 return GF_OK;
    2303             :         case SWF_SETBACKGROUNDCOLOR:
    2304          13 :                 return swf_set_backcol(read);
    2305         751 :         case SWF_DEFINESHAPE:
    2306         751 :                 return swf_parse_shape_def(read, NULL, 0);
    2307         304 :         case SWF_DEFINESHAPE2:
    2308         304 :                 return swf_parse_shape_def(read, NULL, 1);
    2309          49 :         case SWF_DEFINESHAPE3:
    2310          49 :                 return swf_parse_shape_def(read, NULL, 2);
    2311           0 :         case SWF_PLACEOBJECT:
    2312           0 :                 return swf_place_obj(read, 0);
    2313        5388 :         case SWF_PLACEOBJECT2:
    2314        5388 :                 return swf_place_obj(read, 1);
    2315           0 :         case SWF_REMOVEOBJECT:
    2316           0 :                 return swf_remove_obj(read, 0);
    2317         593 :         case SWF_REMOVEOBJECT2:
    2318         593 :                 return swf_remove_obj(read, 1);
    2319             :         case SWF_SHOWFRAME:
    2320        3302 :                 return swf_show_frame(read);
    2321          11 :         case SWF_DEFINEFONT:
    2322          11 :                 return swf_def_font(read, 0);
    2323          14 :         case SWF_DEFINEFONT2:
    2324          14 :                 return swf_def_font(read, 1);
    2325          11 :         case SWF_DEFINEFONTINFO:
    2326          11 :                 return swf_def_font_info(read);
    2327          81 :         case SWF_DEFINETEXT:
    2328          81 :                 return swf_def_text(read, 0);
    2329           0 :         case SWF_DEFINETEXT2:
    2330           0 :                 return swf_def_text(read, 1);
    2331           4 :         case SWF_DEFINEEDITTEXT:
    2332           4 :                 return swf_def_edit_text(read);
    2333          18 :         case SWF_DEFINESPRITE:
    2334          18 :                 return swf_def_sprite(read);
    2335             :         /*no revision needed*/
    2336           2 :         case SWF_SOUNDSTREAMHEAD:
    2337             :         case SWF_SOUNDSTREAMHEAD2:
    2338           2 :                 return swf_soundstream_hdr(read);
    2339           2 :         case SWF_DEFINESOUND:
    2340           2 :                 return swf_def_sound(read);
    2341           2 :         case SWF_STARTSOUND:
    2342           2 :                 return swf_start_sound(read);
    2343         336 :         case SWF_SOUNDSTREAMBLOCK:
    2344         336 :                 return swf_soundstream_block(read);
    2345             : 
    2346           0 :         case SWF_DEFINEBUTTON:
    2347           0 :                 return swf_def_button(read, 0);
    2348           8 :         case SWF_DEFINEBUTTON2:
    2349           8 :                 return swf_def_button(read, 1);
    2350             : //      case SWF_DEFINEBUTTONSOUND:
    2351          12 :         case SWF_DOACTION:
    2352          12 :                 return swf_actions(read, 0, 0);
    2353           0 :         case SWF_FRAMELABEL:
    2354             :         {
    2355           0 :                 char *framelabel = swf_get_string(read);
    2356           0 :                 gf_free(framelabel);
    2357           0 :                 return GF_OK;
    2358             :         }
    2359             : 
    2360           0 :         case SWF_JPEGTABLES:
    2361           0 :                 return swf_def_hdr_jpeg(read);
    2362           0 :         case SWF_DEFINEBITSJPEG:
    2363           0 :                 return swf_def_bits_jpeg(read, 1);
    2364           2 :         case SWF_DEFINEBITSJPEG2:
    2365           2 :                 return swf_def_bits_jpeg(read, 2);
    2366           0 :         case SWF_DEFINEBITSJPEG3:
    2367           0 :                 return swf_def_bits_jpeg(read, 3);
    2368             : 
    2369           0 :         default:
    2370           0 :                 return swf_unknown_tag(read);
    2371             :         }
    2372             : }
    2373             : 
    2374       10925 : GF_Err swf_parse_tag(SWFReader *read)
    2375             : {
    2376             :         GF_Err e;
    2377             :         s32 diff;
    2378             :         u16 hdr;
    2379             :         u32 pos;
    2380             : 
    2381             : 
    2382             :         hdr = swf_get_16(read);
    2383       10925 :         read->tag = hdr>>6;
    2384       10925 :         read->size = hdr & 0x3f;
    2385       10925 :         if (read->size == 0x3f) {
    2386        1575 :                 swf_align(read);
    2387        1575 :                 read->size = swf_get_32(read);
    2388             :         }
    2389       10925 :         pos = swf_get_file_pos(read);
    2390       10925 :         diff = pos + read->size;
    2391       10925 :         gf_set_progress("SWF Parsing", pos, read->length);
    2392             : 
    2393       10925 :         e = swf_process_tag(read);
    2394       10925 :         swf_align(read);
    2395             : 
    2396       21850 :         diff -= swf_get_file_pos(read);
    2397       10925 :         if (diff<0) {
    2398           0 :                 swf_report(read, GF_IO_ERR, "tag %s over-read of %d bytes (size %d)", swf_get_tag_name(read->tag), -1*diff, read->size);
    2399           0 :                 return GF_IO_ERR;
    2400             :         } else {
    2401       10925 :                 swf_read_int(read, diff*8);
    2402             :         }
    2403             : 
    2404             : 
    2405       10925 :         if (!e && !read->tag) {
    2406             :                 return GF_EOS;
    2407             :         }
    2408             : 
    2409       10903 :         if (read->ioerr) {
    2410           0 :                 swf_report(read, GF_IO_ERR, "bitstream IO err (tag size %d)", read->size);
    2411           0 :                 return read->ioerr;
    2412             :         }
    2413             :         return e;
    2414             : }
    2415             : 
    2416             : 
    2417             : 
    2418           9 : GF_Err swf_parse_sprite(SWFReader *read)
    2419             : {
    2420             :         /*parse*/
    2421             :         while (1) {
    2422         137 :                 GF_Err e = swf_parse_tag(read);
    2423         137 :                 if (e<0) {
    2424           0 :                         swf_report(read, e, "Error parsing tag %s", swf_get_tag_name(read->tag));
    2425           0 :                         return e;
    2426             :                 }
    2427             :                 /*done with sprite*/
    2428         137 :                 if (read->tag==SWF_END) break;
    2429             :         }
    2430             :         return GF_OK;
    2431             : }
    2432             : 
    2433             : 
    2434        1482 : void swf_report(SWFReader *read, GF_Err e, char *format, ...)
    2435             : {
    2436             : #ifndef GPAC_DISABLE_LOG
    2437        1482 :         if (gf_log_tool_level_on(GF_LOG_PARSER, e ? GF_LOG_ERROR : GF_LOG_WARNING)) {
    2438             :                 char szMsg[2048];
    2439             :                 va_list args;
    2440        1482 :                 va_start(args, format);
    2441             :                 vsnprintf(szMsg, 2048, format, args);
    2442        1482 :                 va_end(args);
    2443        1482 :                 GF_LOG((u32) (e ? GF_LOG_ERROR : GF_LOG_WARNING), GF_LOG_PARSER, ("[SWF Parsing] %s (frame %d)\n", szMsg, read->current_frame+1) );
    2444             :         }
    2445             : #endif
    2446        1482 : }
    2447             : 
    2448             : 
    2449           0 : static void swf_io_error(void *par)
    2450             : {
    2451             :         SWFReader *read = (SWFReader *)par;
    2452           0 :         if (read) read->ioerr = GF_IO_ERR;
    2453           0 : }
    2454             : 
    2455           8 : GF_Err gf_sm_load_run_swf(GF_SceneLoader *load)
    2456             : {
    2457             :         GF_Err e;
    2458           8 :         SWFReader *read = (SWFReader *)load->loader_priv;
    2459           8 :         if (!read) return GF_BAD_PARAM;
    2460             : 
    2461             :         /*parse all tags*/
    2462             :         while (1) {
    2463        7734 :                 e = swf_parse_tag(read);
    2464        7734 :                 if (e) break;
    2465             :         }
    2466           8 :         gf_set_progress("SWF Parsing", read->length, read->length);
    2467             : 
    2468           8 :         if (e==GF_EOS) {
    2469           8 :                 if (read->finalize)
    2470           8 :                         read->finalize(read);
    2471             :                 e = GF_OK;
    2472             :         }
    2473             :         if (!e) {
    2474           8 :                 if (read->flat_limit != 0)
    2475           0 :                         swf_report(read, GF_OK, "%d points removed while parsing shapes (Flattening limit %.4f)", read->flatten_points, read->flat_limit);
    2476             : 
    2477           8 :                 if (read->no_as && read->has_interact) swf_report(read, GF_OK, "ActionScripts and interactions have been removed");
    2478             :         } else
    2479           0 :                 swf_report(read, e, "Error parsing tag %s", swf_get_tag_name(read->tag));
    2480             : 
    2481             : 
    2482             :         return e;
    2483             : }
    2484             : 
    2485         119 : void gf_swf_reader_del(SWFReader *read)
    2486             : {
    2487         119 :         if (!read) return;
    2488          13 :         gf_bs_del(read->bs);
    2489          13 :         if (read->mem) gf_free(read->mem);
    2490             : 
    2491         170 :         while (gf_list_count(read->display_list)) {
    2492         157 :                 DispShape *s = (DispShape *)gf_list_get(read->display_list, 0);
    2493         157 :                 gf_list_rem(read->display_list, 0);
    2494         157 :                 gf_free(s);
    2495             :         }
    2496          13 :         gf_list_del(read->display_list);
    2497          51 :         while (gf_list_count(read->fonts)) {
    2498          25 :                 SWFFont *ft = (SWFFont *)gf_list_get(read->fonts, 0);
    2499          25 :                 gf_list_rem(read->fonts, 0);
    2500          25 :                 if (ft->glyph_adv) gf_free(ft->glyph_adv);
    2501          25 :                 if (ft->glyph_codes) gf_free(ft->glyph_codes);
    2502          25 :                 if (ft->fontName) gf_free(ft->fontName);
    2503          25 :                 gf_list_del(ft->glyphs);
    2504          25 :                 gf_free(ft);
    2505             :         }
    2506          13 :         gf_list_del(read->fonts);
    2507          13 :         gf_list_del(read->apps);
    2508             : 
    2509          28 :         while (gf_list_count(read->sounds)) {
    2510           2 :                 SWFSound *snd = (SWFSound *)gf_list_get(read->sounds, 0);
    2511           2 :                 gf_list_rem(read->sounds, 0);
    2512           2 :                 if (snd->output) gf_fclose(snd->output);
    2513           2 :                 if (snd->szFileName) gf_free(snd->szFileName);
    2514           2 :                 gf_free(snd);
    2515             :         }
    2516          13 :         gf_list_del(read->sounds);
    2517          13 :         swf_delete_sound_stream(read);
    2518             : 
    2519          13 :         if (read->jpeg_hdr) gf_free(read->jpeg_hdr);
    2520          13 :         if (read->localPath) gf_free(read->localPath);
    2521          13 :         gf_fclose(read->input);
    2522          13 :         gf_free(read->inputName);
    2523          13 :         gf_free(read);
    2524             : }
    2525             : 
    2526           8 : void gf_sm_load_done_swf(GF_SceneLoader *load)
    2527             : {
    2528           8 :         SWFReader *read = (SWFReader *) load->loader_priv;
    2529           8 :         if (!read) return;
    2530           8 :         if (read->svg_file) {
    2531           1 :                 gf_fclose(read->svg_file);
    2532           1 :                 read->svg_file = NULL;
    2533             :         }
    2534           8 :         gf_swf_reader_del(read);
    2535           8 :         load->loader_priv = NULL;
    2536             : }
    2537             : 
    2538          13 : SWFReader *gf_swf_reader_new(const char *localPath, const char *inputName)
    2539             : {
    2540             :         SWFReader *read;
    2541             :         FILE *input;
    2542          13 :         input = gf_fopen(inputName, "rb");
    2543          13 :         if (!input) return NULL;
    2544             : 
    2545          13 :         GF_SAFEALLOC(read, SWFReader);
    2546          13 :         if (!read) return NULL;
    2547          13 :         read->inputName = gf_strdup(inputName);
    2548          13 :         read->input = input;
    2549          13 :         read->bs = gf_bs_from_file(input, GF_BITSTREAM_READ);
    2550          13 :         gf_bs_set_eos_callback(read->bs, swf_io_error, &read);
    2551          13 :         read->display_list = gf_list_new();
    2552          13 :         read->fonts = gf_list_new();
    2553          13 :         read->apps = gf_list_new();
    2554          13 :         read->sounds = gf_list_new();
    2555             : 
    2556          13 :         if (localPath) {
    2557           0 :                 read->localPath = gf_strdup(localPath);
    2558             :         } else {
    2559             :                 char *c;
    2560          13 :                 read->localPath = gf_strdup(inputName);
    2561          13 :                 c = strrchr(read->localPath, GF_PATH_SEPARATOR);
    2562          13 :                 if (c) c[1] = 0;
    2563             :                 else {
    2564           0 :                         gf_free(read->localPath);
    2565           0 :                         read->localPath = NULL;
    2566             :                 }
    2567             :         }
    2568             : 
    2569          13 :         return read;
    2570             : }
    2571             : 
    2572           5 : GF_Err gf_swf_reader_set_user_mode(SWFReader *read, void *user,
    2573             :                                    GF_Err (*add_sample)(void *user, const u8 *data, u32 length, u64 timestamp, Bool isRap),
    2574             :                                    GF_Err (*add_header)(void *user, const u8 *data, u32 length, Bool isHeader))
    2575             : {
    2576           5 :         if (!read) return GF_BAD_PARAM;
    2577           6 :         read->user = user;
    2578           6 :         read->add_header = add_header;
    2579           6 :         read->add_sample = add_sample;
    2580           5 :         return GF_OK;
    2581             : }
    2582             : 
    2583          13 : GF_Err gf_swf_read_header(SWFReader *read)
    2584             : {
    2585             :         SWFRec rc;
    2586             :         u8 sig[3];
    2587             : 
    2588             :         /*get signature*/
    2589          13 :         sig[0] = gf_bs_read_u8(read->bs);
    2590          13 :         sig[1] = gf_bs_read_u8(read->bs);
    2591          13 :         sig[2] = gf_bs_read_u8(read->bs);
    2592             :         /*"FWS" or "CWS"*/
    2593          13 :         if ( ((sig[0] != 'F') && (sig[0] != 'C')) || (sig[1] != 'W') || (sig[2] != 'S') ) {
    2594             :                 return GF_URL_ERROR;
    2595             :         }
    2596          13 :         /*version = */gf_bs_read_u8(read->bs);
    2597          13 :         read->length = swf_get_32(read);
    2598             : 
    2599             :         /*if compressed decompress the whole file*/
    2600          13 :         if (sig[0] == 'C') {
    2601           6 :                 swf_init_decompress(read);
    2602             :         }
    2603             : 
    2604          13 :         swf_get_rec(read, &rc);
    2605          13 :         read->width = rc.w;
    2606          13 :         read->height = rc.h;
    2607             : 
    2608          13 :         swf_align(read);
    2609          13 :         read->frame_rate = swf_get_16(read)>>8;
    2610          13 :         read->frame_count = swf_get_16(read);
    2611          13 :         GF_LOG(GF_LOG_INFO, GF_LOG_PARSER, ("SWF Import - Scene Size %gx%g - %d frames @ %d FPS\n", read->width, read->height, read->frame_count, read->frame_rate));
    2612             :         return GF_OK;
    2613             : }
    2614             : 
    2615           5 : GF_Err gf_swf_get_duration(SWFReader *read, u32 *frame_rate, u32 *frame_count)
    2616             : {
    2617           5 :         *frame_rate = read->frame_rate;
    2618           5 :         *frame_count = read->frame_count;
    2619           5 :         return GF_OK;
    2620             : }
    2621             : 
    2622           8 : GF_Err gf_sm_load_init_swf(GF_SceneLoader *load)
    2623             : {
    2624             :         SWFReader *read;
    2625             :         GF_Err e;
    2626             : 
    2627           8 :         if (!load->ctx || !load->scene_graph || !load->fileName) return GF_BAD_PARAM;
    2628             : 
    2629             : #ifdef GPAC_ENABLE_COVERAGE
    2630           8 :         if (gf_sys_is_cov_mode()) {
    2631             :                 swf_func_skip(NULL);
    2632             :                 swf_def_hdr_jpeg(NULL);
    2633             :                 swf_get_tag_name(SWF_FREECHARACTER);
    2634             :                 swf_unknown_tag(NULL);
    2635             :                 swf_io_error(NULL);
    2636             :         }
    2637             : #endif
    2638             : 
    2639           8 :         read = gf_swf_reader_new(load->localPath, load->fileName);
    2640           8 :         read->load = load;
    2641           8 :         read->flags = load->swf_import_flags;
    2642           8 :         read->flat_limit = FLT2FIX(load->swf_flatten_limit);
    2643           8 :         load->loader_priv = read;
    2644             : 
    2645           8 :         gf_swf_read_header(read);
    2646           8 :         load->ctx->scene_width = FIX2INT(read->width);
    2647           8 :         load->ctx->scene_height = FIX2INT(read->height);
    2648           8 :         load->ctx->is_pixel_metrics = 1;
    2649             : 
    2650           8 :         if (!(load->swf_import_flags & GF_SM_SWF_SPLIT_TIMELINE) ) {
    2651           2 :                 swf_report(read, GF_OK, "ActionScript disabled");
    2652           2 :                 read->no_as = 1;
    2653             :         }
    2654             : 
    2655           8 :         if (!(load->swf_import_flags & GF_SM_SWF_USE_SVG)) {
    2656             : #ifndef GPAC_DISABLE_VRML
    2657           7 :                 e = swf_to_bifs_init(read);
    2658             : #else
    2659             :                 e = GF_NOT_SUPPORTED;
    2660             : #endif
    2661             :         } else {
    2662             : #ifndef GPAC_DISABLE_SVG
    2663             :                 FILE *svgFile;
    2664           1 :                 if (load->svgOutFile) {
    2665             :                         char svgFileName[GF_MAX_PATH];
    2666           1 :                         if (load->localPath) {
    2667             :                                 sprintf(svgFileName, "%s%c%s.svg", load->localPath, GF_PATH_SEPARATOR, load->svgOutFile);
    2668             :                         } else {
    2669             :                                 sprintf(svgFileName, "%s.svg", load->svgOutFile);
    2670             :                         }
    2671           1 :                         svgFile = gf_fopen(svgFileName, "wt");
    2672           1 :                         if (!svgFile) return GF_BAD_PARAM;
    2673           1 :                         read->svg_file = svgFile;
    2674             :                 } else {
    2675           0 :                         svgFile = stdout;
    2676             :                 }
    2677             :                 gf_swf_reader_set_user_mode(read, svgFile, swf_svg_write_text_sample, swf_svg_write_text_header);
    2678           1 :                 e = swf_to_svg_init(read, read->flags, load->swf_flatten_limit);
    2679             : #else
    2680             :                 e = GF_NOT_SUPPORTED;
    2681             : #endif
    2682             :         }
    2683           8 :         if (e) goto exit;
    2684             : 
    2685             :         /*parse all tags*/
    2686         138 :         while (e == GF_OK) {
    2687         138 :                 e = swf_parse_tag(read);
    2688         138 :                 if (read->current_frame==1) break;
    2689             :         }
    2690           8 :         if (e==GF_EOS) e = GF_OK;
    2691             : 
    2692           8 :         load->done = gf_sm_load_done_swf;
    2693           8 :         load->process = gf_sm_load_run_swf;
    2694             : 
    2695           8 : exit:
    2696           8 :         if (e) gf_sm_load_done_swf(load);
    2697             :         return e;
    2698             : }
    2699             : 
    2700             : #endif /*GPAC_DISABLE_SWF_IMPORT*/

Generated by: LCOV version 1.13