data.py 53 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437
  1. from .consts import *
  2. from .utils import *
  3. class _dumb_repr(object):
  4. def __repr__(self):
  5. return '<%s %r>' % (self.__class__.__name__, self.__dict__)
  6. class SWFRawTag(_dumb_repr):
  7. def __init__(self, s=None):
  8. if not s is None:
  9. self.parse(s)
  10. def parse(self, s):
  11. pos = s.tell()
  12. self.header = s.readtag_header()
  13. self.pos_content = s.tell()
  14. s.f.seek(pos)
  15. #self.bytes = s.f.read(self.header.tag_length())
  16. #s.f.seek(self.pos_content)
  17. class SWFStraightEdge(_dumb_repr):
  18. def __init__(self, start, to, line_style_idx, fill_style_idx):
  19. self.start = start
  20. self.to = to
  21. self.line_style_idx = line_style_idx
  22. self.fill_style_idx = fill_style_idx
  23. def reverse_with_new_fillstyle(self, new_fill_idx):
  24. return SWFStraightEdge(self.to, self.start, self.line_style_idx, new_fill_idx)
  25. class SWFCurvedEdge(SWFStraightEdge):
  26. def __init__(self, start, control, to, line_style_idx, fill_style_idx):
  27. super(SWFCurvedEdge, self).__init__(start, to, line_style_idx, fill_style_idx)
  28. self.control = control
  29. def reverse_with_new_fillstyle(self, new_fill_idx):
  30. return SWFCurvedEdge(self.to, self.control, self.start, self.line_style_idx, new_fill_idx)
  31. class SWFShape(_dumb_repr):
  32. def __init__(self, data=None, level=1, unit_divisor=20.0):
  33. self._records = []
  34. self._fillStyles = []
  35. self._lineStyles = []
  36. self._postLineStyles = {}
  37. self._edgeMapsCreated = False
  38. self.unit_divisor = unit_divisor
  39. self.fill_edge_maps = []
  40. self.line_edge_maps = []
  41. self.current_fill_edge_map = {}
  42. self.current_line_edge_map = {}
  43. self.num_groups = 0
  44. self.coord_map = {}
  45. if not data is None:
  46. self.parse(data, level)
  47. def get_dependencies(self):
  48. s = set()
  49. for x in self._fillStyles:
  50. s.update(x.get_dependencies())
  51. for x in self._lineStyles:
  52. s.update(x.get_dependencies())
  53. return s
  54. def parse(self, data, level=1):
  55. data.reset_bits_pending()
  56. fillbits = data.readUB(4)
  57. linebits = data.readUB(4)
  58. self.read_shape_records(data, fillbits, linebits, level)
  59. def export(self, handler=None):
  60. self._create_edge_maps()
  61. if handler is None:
  62. from export import SVGShapeExporter
  63. handler = SVGShapeExporter()
  64. handler.begin_shape()
  65. for i in range(0, self.num_groups):
  66. self._export_fill_path(handler, i)
  67. self._export_line_path(handler, i)
  68. handler.end_shape()
  69. return handler
  70. @property
  71. def records(self):
  72. return self._records
  73. def read_shape_records(self, data, fill_bits, line_bits, level=1):
  74. shape_record = None
  75. record_id = 0
  76. while type(shape_record) != SWFShapeRecordEnd:
  77. # The SWF10 spec says that shape records are byte aligned.
  78. # In reality they seem not to be?
  79. # bitsPending = 0;
  80. edge_record = (data.readUB(1) == 1)
  81. if edge_record:
  82. straight_flag = (data.readUB(1) == 1)
  83. num_bits = data.readUB(4) + 2
  84. if straight_flag:
  85. shape_record = data.readSTRAIGHTEDGERECORD(num_bits)
  86. else:
  87. shape_record = data.readCURVEDEDGERECORD(num_bits)
  88. else:
  89. states= data.readUB(5)
  90. if states == 0:
  91. shape_record = SWFShapeRecordEnd()
  92. else:
  93. style_change_record = data.readSTYLECHANGERECORD(states, fill_bits, line_bits, level)
  94. if style_change_record.state_new_styles:
  95. fill_bits = style_change_record.num_fillbits
  96. line_bits = style_change_record.num_linebits
  97. shape_record = style_change_record
  98. shape_record.record_id = record_id
  99. self._records.append(shape_record)
  100. record_id += 1
  101. #print shape_record.tostring()
  102. def _create_edge_maps(self):
  103. if self._edgeMapsCreated:
  104. return
  105. xPos = 0
  106. yPos = 0
  107. sub_path = []
  108. fs_offset = 0
  109. ls_offset = 0
  110. curr_fs_idx0 = 0
  111. curr_fs_idx1 = 0
  112. curr_ls_idx = 0
  113. self.fill_edge_maps = []
  114. self.line_edge_maps = []
  115. self.current_fill_edge_map = {}
  116. self.current_line_edge_map = {}
  117. self.num_groups = 0
  118. for i in range(0, len(self._records)):
  119. rec = self._records[i]
  120. if rec.type == SWFShapeRecord.TYPE_STYLECHANGE:
  121. if rec.state_line_style or rec.state_fill_style0 or rec.state_fill_style1:
  122. if len(sub_path):
  123. self._process_sub_path(sub_path, curr_ls_idx, curr_fs_idx0, curr_fs_idx1, rec.record_id)
  124. sub_path = []
  125. if rec.state_new_styles:
  126. fs_offset = len(self._fillStyles)
  127. ls_offset = len(self._lineStyles)
  128. self._append_to(self._fillStyles, rec.fill_styles)
  129. self._append_to(self._lineStyles, rec.line_styles)
  130. if rec.state_line_style and rec.state_fill_style0 and rec.state_fill_style1 and \
  131. rec.line_style == 0 and rec.fill_style0 == 0 and rec.fill_style1 == 0:
  132. # new group (probably)
  133. self._clean_edge_map(self.current_fill_edge_map)
  134. self._clean_edge_map(self.current_line_edge_map)
  135. self.fill_edge_maps.append(self.current_fill_edge_map)
  136. self.line_edge_maps.append(self.current_line_edge_map)
  137. self.current_fill_edge_map = {}
  138. self.current_line_edge_map = {}
  139. self.num_groups += 1
  140. curr_fs_idx0 = 0
  141. curr_fs_idx1 = 0
  142. curr_ls_idx = 0
  143. else:
  144. if rec.state_line_style:
  145. curr_ls_idx = rec.line_style
  146. if curr_ls_idx > 0:
  147. curr_ls_idx += ls_offset
  148. if rec.state_fill_style0:
  149. curr_fs_idx0 = rec.fill_style0
  150. if curr_fs_idx0 > 0:
  151. curr_fs_idx0 += fs_offset
  152. if rec.state_fill_style1:
  153. curr_fs_idx1 = rec.fill_style1
  154. if curr_fs_idx1 > 0:
  155. curr_fs_idx1 += fs_offset
  156. if rec.state_moveto:
  157. xPos = rec.move_deltaX
  158. yPos = rec.move_deltaY
  159. elif rec.type == SWFShapeRecord.TYPE_STRAIGHTEDGE:
  160. start = [NumberUtils.round_pixels_400(xPos), NumberUtils.round_pixels_400(yPos)]
  161. if rec.general_line_flag:
  162. xPos += rec.deltaX
  163. yPos += rec.deltaY
  164. else:
  165. if rec.vert_line_flag:
  166. yPos += rec.deltaY
  167. else:
  168. xPos += rec.deltaX
  169. to = [NumberUtils.round_pixels_400(xPos), NumberUtils.round_pixels_400(yPos)]
  170. sub_path.append(SWFStraightEdge(start, to, curr_ls_idx, curr_fs_idx1))
  171. elif rec.type == SWFShapeRecord.TYPE_CURVEDEDGE:
  172. start = [NumberUtils.round_pixels_400(xPos), NumberUtils.round_pixels_400(yPos)]
  173. xPosControl = xPos + rec.control_deltaX
  174. yPosControl = yPos + rec.control_deltaY
  175. xPos = xPosControl + rec.anchor_deltaX
  176. yPos = yPosControl + rec.anchor_deltaY
  177. control = [xPosControl, yPosControl]
  178. to = [NumberUtils.round_pixels_400(xPos), NumberUtils.round_pixels_400(yPos)]
  179. sub_path.append(SWFCurvedEdge(start, control, to, curr_ls_idx, curr_fs_idx1))
  180. elif rec.type == SWFShapeRecord.TYPE_END:
  181. # We're done. Process the last subpath, if any
  182. if len(sub_path) > 0:
  183. self._process_sub_path(sub_path, curr_ls_idx, curr_fs_idx0, curr_fs_idx1, rec.record_id)
  184. self._clean_edge_map(self.current_fill_edge_map)
  185. self._clean_edge_map(self.current_line_edge_map)
  186. self.fill_edge_maps.append(self.current_fill_edge_map)
  187. self.line_edge_maps.append(self.current_line_edge_map)
  188. self.current_fill_edge_map = {}
  189. self.current_line_edge_map = {}
  190. self.num_groups += 1
  191. curr_fs_idx0 = 0
  192. curr_fs_idx1 = 0
  193. curr_ls_idx = 0
  194. self._edgeMapsCreated = True
  195. def _process_sub_path(self, sub_path, linestyle_idx, fillstyle_idx0, fillstyle_idx1, record_id=-1):
  196. path = None
  197. if fillstyle_idx0 != 0:
  198. if not fillstyle_idx0 in self.current_fill_edge_map:
  199. path = self.current_fill_edge_map[fillstyle_idx0] = []
  200. else:
  201. path = self.current_fill_edge_map[fillstyle_idx0]
  202. for j in range(len(sub_path) - 1, -1, -1):
  203. path.append(sub_path[j].reverse_with_new_fillstyle(fillstyle_idx0))
  204. if fillstyle_idx1 != 0:
  205. if not fillstyle_idx1 in self.current_fill_edge_map:
  206. path = self.current_fill_edge_map[fillstyle_idx1] = []
  207. else:
  208. path = self.current_fill_edge_map[fillstyle_idx1]
  209. self._append_to(path, sub_path)
  210. if linestyle_idx != 0:
  211. if not linestyle_idx in self.current_line_edge_map:
  212. path = self.current_line_edge_map[linestyle_idx] = []
  213. else:
  214. path = self.current_line_edge_map[linestyle_idx]
  215. self._append_to(path, sub_path)
  216. def _clean_edge_map(self, edge_map):
  217. for style_idx in edge_map:
  218. sub_path = edge_map[style_idx] if style_idx in edge_map else None
  219. if sub_path is not None and len(sub_path) > 0:
  220. tmp_path = []
  221. prev_edge = None
  222. self._create_coord_map(sub_path)
  223. while len(sub_path) > 0:
  224. idx = 0
  225. while idx < len(sub_path):
  226. if prev_edge is None or self._equal_point(prev_edge.to, sub_path[idx].start):
  227. edge = sub_path[idx]
  228. del sub_path[idx]
  229. tmp_path.append(edge)
  230. self._remove_edge_from_coord_map(edge)
  231. prev_edge = edge
  232. else:
  233. edge = self._find_next_edge_in_coord_map(prev_edge)
  234. if not edge is None:
  235. idx = sub_path.index(edge)
  236. else:
  237. idx = 0
  238. prev_edge = None
  239. edge_map[style_idx] = tmp_path
  240. def _equal_point(self, a, b, tol=0.001):
  241. return (a[0] > b[0]-tol and a[0] < b[0]+tol and a[1] > b[1]-tol and a[1] < b[1]+tol)
  242. def _find_next_edge_in_coord_map(self, edge):
  243. key = "%0.4f_%0.4f" % (edge.to[0], edge.to[1])
  244. if key in self.coord_map and len(self.coord_map[key]) > 0:
  245. return self.coord_map[key][0]
  246. else:
  247. return None
  248. def _create_coord_map(self, path):
  249. self.coord_map = {}
  250. for i in range(0, len(path)):
  251. start = path[i].start
  252. key = "%0.4f_%0.4f" % (start[0], start[1])
  253. coord_map_array = self.coord_map[key] if key in self.coord_map else None
  254. if coord_map_array is None:
  255. self.coord_map[key] = [path[i]]
  256. else:
  257. self.coord_map[key].append(path[i])
  258. def _remove_edge_from_coord_map(self, edge):
  259. key = "%0.4f_%0.4f" % (edge.start[0], edge.start[1])
  260. if key in self.coord_map:
  261. coord_map_array = self.coord_map[key]
  262. if len(coord_map_array) == 1:
  263. del self.coord_map[key]
  264. else:
  265. try:
  266. idx = coord_map_array.index(edge)
  267. del coord_map_array[idx]
  268. except:
  269. pass
  270. def _create_path_from_edge_map(self, edge_map):
  271. new_path = []
  272. style_ids = []
  273. for style_id in edge_map:
  274. style_ids.append(int(style_id))
  275. style_ids = sorted(style_ids)
  276. for i in range(0, len(style_ids)):
  277. self._append_to(new_path, edge_map[style_ids[i]])
  278. return new_path
  279. def _export_fill_path(self, handler, group_index):
  280. path = self._create_path_from_edge_map(self.fill_edge_maps[group_index])
  281. pos = [100000000, 100000000]
  282. u = 1.0 / self.unit_divisor
  283. fill_style_idx = 10000000
  284. if len(path) < 1:
  285. return
  286. handler.begin_fills()
  287. for i in range(0, len(path)):
  288. e = path[i]
  289. if fill_style_idx != e.fill_style_idx:
  290. fill_style_idx = e.fill_style_idx
  291. pos = [100000000, 100000000]
  292. try:
  293. fill_style = self._fillStyles[fill_style_idx - 1] if fill_style_idx > 0 else None
  294. if fill_style.type == 0x0:
  295. # solid fill
  296. handler.begin_fill(
  297. ColorUtils.rgb(fill_style.rgb),
  298. ColorUtils.alpha(fill_style.rgb))
  299. elif fill_style.type in [0x10, 0x12, 0x13]:
  300. # gradient fill
  301. colors = []
  302. ratios = []
  303. alphas = []
  304. for j in range(0, len(fill_style.gradient.records)):
  305. gr = fill_style.gradient.records[j]
  306. colors.append(ColorUtils.rgb(gr.color))
  307. ratios.append(gr.ratio)
  308. alphas.append(ColorUtils.alpha(gr.color))
  309. handler.begin_gradient_fill(
  310. GradientType.LINEAR if fill_style.type == 0x10 else GradientType.RADIAL,
  311. colors, alphas, ratios,
  312. fill_style.gradient_matrix,
  313. fill_style.gradient.spreadmethod,
  314. fill_style.gradient.interpolation_mode,
  315. fill_style.gradient.focal_point
  316. )
  317. elif fill_style.type in [0x40, 0x41, 0x42, 0x43]:
  318. # bitmap fill
  319. handler.begin_bitmap_fill(
  320. fill_style.bitmap_id,
  321. fill_style.bitmap_matrix,
  322. (fill_style.type == 0x40 or fill_style.type == 0x42),
  323. (fill_style.type == 0x40 or fill_style.type == 0x41)
  324. )
  325. pass
  326. except:
  327. # Font shapes define no fillstyles per se, but do reference fillstyle index 1,
  328. # which represents the font color. We just report solid black in this case.
  329. handler.begin_fill(0)
  330. if not self._equal_point(pos, e.start):
  331. handler.move_to(e.start[0] * u, e.start[1] * u)
  332. if type(e) is SWFCurvedEdge:
  333. handler.curve_to(e.control[0] * u, e.control[1] * u, e.to[0] * u, e.to[1] * u)
  334. else:
  335. handler.line_to(e.to[0] * u, e.to[1] * u)
  336. pos = e.to
  337. handler.end_fill()
  338. handler.end_fills()
  339. def _export_line_path(self, handler, group_index):
  340. path = self._create_path_from_edge_map(self.line_edge_maps[group_index])
  341. pos = [100000000, 100000000]
  342. u = 1.0 / self.unit_divisor
  343. line_style_idx = 10000000
  344. line_style = None
  345. if len(path) < 1:
  346. return
  347. handler.begin_lines()
  348. for i in range(0, len(path)):
  349. e = path[i]
  350. if line_style_idx != e.line_style_idx:
  351. line_style_idx = e.line_style_idx
  352. pos = [100000000, 100000000]
  353. try:
  354. line_style = self._lineStyles[line_style_idx - 1]
  355. except:
  356. line_style = None
  357. if line_style is not None:
  358. scale_mode = LineScaleMode.NORMAL
  359. if line_style.no_hscale_flag and line_style.no_vscale_flag:
  360. scale_mode = LineScaleMode.NONE
  361. elif line_style.no_hscale_flag:
  362. scale_mode = LineScaleMode.HORIZONTAL
  363. elif line_style.no_hscale_flag:
  364. scale_mode = LineScaleMode.VERTICAL
  365. if not line_style.has_fill_flag:
  366. handler.line_style(
  367. line_style.width / 20.0,
  368. ColorUtils.rgb(line_style.color),
  369. ColorUtils.alpha(line_style.color),
  370. line_style.pixelhinting_flag,
  371. scale_mode,
  372. line_style.start_caps_style,
  373. line_style.end_caps_style,
  374. line_style.joint_style,
  375. line_style.miter_limit_factor)
  376. else:
  377. fill_style = line_style.fill_type
  378. if fill_style.type in [0x10, 0x12, 0x13]:
  379. # gradient fill
  380. colors = []
  381. ratios = []
  382. alphas = []
  383. for j in range(0, len(fill_style.gradient.records)):
  384. gr = fill_style.gradient.records[j]
  385. colors.append(ColorUtils.rgb(gr.color))
  386. ratios.append(gr.ratio)
  387. alphas.append(ColorUtils.alpha(gr.color))
  388. handler.line_gradient_style(
  389. line_style.width / 20.0,
  390. line_style.pixelhinting_flag,
  391. scale_mode,
  392. line_style.start_caps_style,
  393. line_style.end_caps_style,
  394. line_style.joint_style,
  395. line_style.miter_limit_factor,
  396. GradientType.LINEAR if fill_style.type == 0x10 else GradientType.RADIAL,
  397. colors, alphas, ratios,
  398. fill_style.gradient_matrix,
  399. fill_style.gradient.spreadmethod,
  400. fill_style.gradient.interpolation_mode,
  401. fill_style.gradient.focal_point
  402. )
  403. elif fill_style.type in [0x40, 0x41, 0x42]:
  404. handler.line_bitmap_style(
  405. line_style.width / 20.0,
  406. line_style.pixelhinting_flag,
  407. scale_mode,
  408. line_style.start_caps_style,
  409. line_style.end_caps_style,
  410. line_style.joint_style,
  411. line_style.miter_limit_factor,
  412. fill_style.bitmap_id, fill_style.bitmap_matrix,
  413. (fill_style.type == 0x40 or fill_style.type == 0x42),
  414. (fill_style.type == 0x40 or fill_style.type == 0x41)
  415. )
  416. else:
  417. # we should never get here
  418. handler.line_style(0)
  419. if not self._equal_point(pos, e.start):
  420. handler.move_to(e.start[0] * u, e.start[1] * u)
  421. if type(e) is SWFCurvedEdge:
  422. handler.curve_to(e.control[0] * u, e.control[1] * u, e.to[0] * u, e.to[1] * u)
  423. else:
  424. handler.line_to(e.to[0] * u, e.to[1] * u)
  425. pos = e.to
  426. handler.end_lines()
  427. def _append_to(self, v1, v2):
  428. for i in range(0, len(v2)):
  429. v1.append(v2[i])
  430. def __str__(self):
  431. return "[SWFShape]"
  432. class SWFShapeWithStyle(SWFShape):
  433. def __init__(self, data, level, unit_divisor):
  434. self._initialFillStyles = []
  435. self._initialLineStyles = []
  436. super(SWFShapeWithStyle, self).__init__(data, level, unit_divisor)
  437. def export(self, handler=None):
  438. self._fillStyles.extend(self._initialFillStyles)
  439. self._lineStyles.extend(self._initialLineStyles)
  440. return super(SWFShapeWithStyle, self).export(handler)
  441. def get_dependencies(self):
  442. s = set()
  443. for x in self._fillStyles + self._initialFillStyles:
  444. s.update(x.get_dependencies())
  445. for x in self._lineStyles + self._initialLineStyles:
  446. s.update(x.get_dependencies())
  447. return s
  448. def parse(self, data, level=1):
  449. data.reset_bits_pending()
  450. num_fillstyles = self.readstyle_array_length(data, level)
  451. for i in range(0, num_fillstyles):
  452. self._initialFillStyles.append(data.readFILLSTYLE(level))
  453. num_linestyles = self.readstyle_array_length(data, level)
  454. for i in range(0, num_linestyles):
  455. if level <= 3:
  456. self._initialLineStyles.append(data.readLINESTYLE(level))
  457. else:
  458. self._initialLineStyles.append(data.readLINESTYLE2(level))
  459. num_fillbits = data.readUB(4)
  460. num_linebits = data.readUB(4)
  461. data.reset_bits_pending()
  462. self.read_shape_records(data, num_fillbits, num_linebits, level)
  463. def readstyle_array_length(self, data, level=1):
  464. length = data.readUI8()
  465. if level >= 2 and length == 0xff:
  466. length = data.readUI16()
  467. return length
  468. def __str__(self):
  469. s = " FillStyles:\n" if len(self._fillStyles) > 0 else ""
  470. for i in range(0, len(self._initialFillStyles)):
  471. s += " %d:%s\n" % (i+1, self._initialFillStyles[i].__str__())
  472. if len(self._initialLineStyles) > 0:
  473. s += " LineStyles:\n"
  474. for i in range(0, len(self._initialLineStyles)):
  475. s += " %d:%s\n" % (i+1, self._initialLineStyles[i].__str__())
  476. for record in self._records:
  477. s += record.__str__() + '\n'
  478. return s.rstrip() + super(SWFShapeWithStyle, self).__str__()
  479. class SWFShapeRecord(_dumb_repr):
  480. TYPE_UNKNOWN = 0
  481. TYPE_END = 1
  482. TYPE_STYLECHANGE = 2
  483. TYPE_STRAIGHTEDGE = 3
  484. TYPE_CURVEDEDGE = 4
  485. record_id = -1
  486. def __init__(self, data=None, level=1):
  487. if not data is None:
  488. self.parse(data, level)
  489. @property
  490. def is_edge_record(self):
  491. return (self.type == SWFShapeRecord.TYPE_STRAIGHTEDGE or
  492. self.type == SWFShapeRecord.TYPE_CURVEDEDGE)
  493. def parse(self, data, level=1):
  494. pass
  495. @property
  496. def type(self):
  497. return SWFShapeRecord.TYPE_UNKNOWN
  498. def __str__(self):
  499. return " [SWFShapeRecord]"
  500. class SWFShapeRecordStraightEdge(SWFShapeRecord):
  501. def __init__(self, data, num_bits=0, level=1):
  502. self.num_bits = num_bits
  503. super(SWFShapeRecordStraightEdge, self).__init__(data, level)
  504. def parse(self, data, level=1):
  505. self.general_line_flag = (data.readUB(1) == 1)
  506. self.vert_line_flag = False if self.general_line_flag else (data.readUB(1) == 1)
  507. self.deltaX = data.readSB(self.num_bits) \
  508. if self.general_line_flag or not self.vert_line_flag \
  509. else 0.0
  510. self.deltaY = data.readSB(self.num_bits) \
  511. if self.general_line_flag or self.vert_line_flag \
  512. else 0.0
  513. @property
  514. def type(self):
  515. return SWFShapeRecord.TYPE_STRAIGHTEDGE
  516. def __str__(self):
  517. s = " [SWFShapeRecordStraightEdge]"
  518. if self.general_line_flag:
  519. s += " General: %d %d" % (self.deltaX, self.deltaY)
  520. else:
  521. if self.vert_line_flag:
  522. s += " Vertical: %d" % self.deltaY
  523. else:
  524. s += " Horizontal: %d" % self.deltaX
  525. return s
  526. class SWFShapeRecordCurvedEdge(SWFShapeRecord):
  527. def __init__(self, data, num_bits=0, level=1):
  528. self.num_bits = num_bits
  529. super(SWFShapeRecordCurvedEdge, self).__init__(data, level)
  530. def parse(self, data, level=1):
  531. self.control_deltaX = data.readSB(self.num_bits)
  532. self.control_deltaY = data.readSB(self.num_bits)
  533. self.anchor_deltaX = data.readSB(self.num_bits)
  534. self.anchor_deltaY = data.readSB(self.num_bits)
  535. @property
  536. def type(self):
  537. return SWFShapeRecord.TYPE_CURVEDEDGE
  538. def __str__(self):
  539. return " [SWFShapeRecordCurvedEdge]" + \
  540. " ControlDelta: %d, %d" % (self.control_deltaX, self.control_deltaY) + \
  541. " AnchorDelta: %d, %d" % (self.anchor_deltaX, self.anchor_deltaY)
  542. class SWFShapeRecordStyleChange(SWFShapeRecord):
  543. def __init__(self, data, states=0, fill_bits=0, line_bits=0, level=1):
  544. self.fill_styles = []
  545. self.line_styles = []
  546. self.state_new_styles = ((states & 0x10) != 0)
  547. self.state_line_style = ((states & 0x08) != 0)
  548. self.state_fill_style1 = ((states & 0x4) != 0)
  549. self.state_fill_style0 = ((states & 0x2) != 0)
  550. self.state_moveto = ((states & 0x1) != 0)
  551. self.num_fillbits = fill_bits
  552. self.num_linebits = line_bits
  553. self.move_deltaX = 0.0
  554. self.move_deltaY = 0.0
  555. self.fill_style0 = 0
  556. self.fill_style1 = 0
  557. self.line_style = 0
  558. super(SWFShapeRecordStyleChange, self).__init__(data, level)
  559. def parse(self, data, level=1):
  560. if self.state_moveto:
  561. movebits = data.readUB(5)
  562. self.move_deltaX = data.readSB(movebits)
  563. self.move_deltaY = data.readSB(movebits)
  564. self.fill_style0 = data.readUB(self.num_fillbits) if self.state_fill_style0 else 0
  565. self.fill_style1 = data.readUB(self.num_fillbits) if self.state_fill_style1 else 0
  566. self.line_style = data.readUB(self.num_linebits) if self.state_line_style else 0
  567. if self.state_new_styles:
  568. data.reset_bits_pending();
  569. num_fillstyles = self.readstyle_array_length(data, level)
  570. for i in range(0, num_fillstyles):
  571. self.fill_styles.append(data.readFILLSTYLE(level))
  572. num_linestyles = self.readstyle_array_length(data, level)
  573. for i in range(0, num_linestyles):
  574. if level <= 3:
  575. self.line_styles.append(data.readLINESTYLE(level))
  576. else:
  577. self.line_styles.append(data.readLINESTYLE2(level))
  578. self.num_fillbits = data.readUB(4)
  579. self.num_linebits = data.readUB(4)
  580. @property
  581. def type(self):
  582. return SWFShapeRecord.TYPE_STYLECHANGE
  583. def readstyle_array_length(self, data, level=1):
  584. length = data.readUI8()
  585. if level >= 2 and length == 0xff:
  586. length = data.readUI16()
  587. return length
  588. def __str__(self):
  589. return " [SWFShapeRecordStyleChange]" + \
  590. " moveTo: %d %d" % (self.move_deltaX, self.move_deltaY) + \
  591. " fs0: %d" % self.fill_style0 + \
  592. " fs1: %d" % self.fill_style1 + \
  593. " linestyle: %d" % self.line_style + \
  594. " flags: %d %d %d" % (self.state_fill_style0, self.state_fill_style1, self.state_line_style)
  595. class SWFShapeRecordEnd(SWFShapeRecord):
  596. def __init__(self):
  597. super(SWFShapeRecordEnd, self).__init__(None)
  598. def parse(self, data, level=1):
  599. pass
  600. @property
  601. def type(self):
  602. return SWFShapeRecord.TYPE_END
  603. def __str__(self):
  604. return " [SWFShapeRecordEnd]"
  605. class SWFMatrix(_dumb_repr):
  606. def __init__(self, data):
  607. self.scaleX = 1.0
  608. self.scaleY = 1.0
  609. self.rotateSkew0 = 0.0
  610. self.rotateSkew1 = 0.0
  611. self.translateX = 0.0
  612. self.translateY = 0.0
  613. if not data is None:
  614. self.parse(data)
  615. def parse(self, data):
  616. data.reset_bits_pending();
  617. self.scaleX = 1.0
  618. self.scaleY = 1.0
  619. if data.readUB(1) == 1:
  620. scaleBits = data.readUB(5)
  621. self.scaleX = data.readFB(scaleBits)
  622. self.scaleY = data.readFB(scaleBits)
  623. self.rotateSkew0 = 0.0
  624. self.rotateSkew1 = 0.0
  625. if data.readUB(1) == 1:
  626. rotateBits = data.readUB(5)
  627. self.rotateSkew0 = data.readFB(rotateBits)
  628. self.rotateSkew1 = data.readFB(rotateBits)
  629. translateBits = data.readUB(5)
  630. self.translateX = data.readSB(translateBits)
  631. self.translateY = data.readSB(translateBits)
  632. def to_array(self):
  633. return [
  634. self.scaleX, self.rotateSkew0,
  635. self.rotateSkew1, self.scaleY,
  636. self.translateX, self.translateY
  637. ]
  638. def __str__(self):
  639. def fmt(s):
  640. return "%0.2f" % s
  641. return "[%s]" % ",".join(map(fmt, self.to_array()))
  642. class SWFGradientRecord(_dumb_repr):
  643. def __init__(self, data=None, level=1):
  644. self._records = []
  645. if not data is None:
  646. self.parse(data, level)
  647. def parse(self, data, level=1):
  648. self.ratio = data.readUI8()
  649. self.color = data.readRGB() if level <= 2 else data.readRGBA()
  650. def __str__(self):
  651. return "[SWFGradientRecord] Color: %s, Ratio: %d" % (ColorUtils.to_rgb_string(self.color), self.ratio)
  652. class SWFGradient(_dumb_repr):
  653. def __init__(self, data=None, level=1):
  654. self._records = []
  655. self.focal_point = 0.0
  656. if not data is None:
  657. self.parse(data, level)
  658. @property
  659. def records(self):
  660. return self._records
  661. def parse(self, data, level=1):
  662. data.reset_bits_pending();
  663. self.spreadmethod = data.readUB(2)
  664. self.interpolation_mode = data.readUB(2)
  665. num_gradients = data.readUB(4)
  666. for i in range(0, num_gradients):
  667. self._records.append(data.readGRADIENTRECORD(level))
  668. def __str__(self):
  669. s = "[SWFGadient]"
  670. for record in self._records:
  671. s += "\n " + record.__str__()
  672. return s
  673. class SWFFocalGradient(SWFGradient):
  674. def __init__(self, data=None, level=1):
  675. super(SWFFocalGradient, self).__init__(data, level)
  676. def parse(self, data, level=1):
  677. super(SWFFocalGradient, self).parse(data, level)
  678. self.focal_point = data.readFIXED8()
  679. def __str__(self):
  680. return "[SWFFocalGradient] Color: %s, Ratio: %d, Focal: %0.2f" % \
  681. (ColorUtils.to_rgb_string(self.color), self.ratio, self.focal_point)
  682. class SWFFillStyle(_dumb_repr):
  683. def __init__(self, data=None, level=1):
  684. if not data is None:
  685. self.parse(data, level)
  686. COLOR = [0x0]
  687. GRADIENT = [0x10, 0x12, 0x13]
  688. BITMAP = [0x40, 0x41, 0x42, 0x43]
  689. def parse(self, data, level=1):
  690. self.type = data.readUI8()
  691. if self.type in SWFFillStyle.COLOR:
  692. self.rgb = data.readRGB() if level <= 2 else data.readRGBA()
  693. elif self.type in SWFFillStyle.GRADIENT:
  694. self.gradient_matrix = data.readMATRIX()
  695. self.gradient = data.readFOCALGRADIENT(level) if self.type == 0x13 else data.readGRADIENT(level)
  696. elif self.type in SWFFillStyle.BITMAP:
  697. self.bitmap_id = data.readUI16()
  698. self.bitmap_matrix = data.readMATRIX()
  699. else:
  700. raise Exception("Unknown fill style type: 0x%x" % self.type, level)
  701. def get_dependencies(self):
  702. return set([self.bitmap_id]) if self.type in SWFFillStyle.BITMAP else set()
  703. def __str__(self):
  704. s = "[SWFFillStyle] "
  705. if self.type in SWFFillStyle.COLOR:
  706. s += "Color: %s" % ColorUtils.to_rgb_string(self.rgb)
  707. elif self.type in SWFFillStyle.GRADIENT:
  708. s += "Gradient: %s" % self.gradient_matrix
  709. elif self.type in SWFFillStyle.BITMAP:
  710. s += "BitmapID: %d" % (self.bitmap_id)
  711. return s
  712. class SWFLineStyle(_dumb_repr):
  713. def __init__(self, data=None, level=1):
  714. # forward declarations for SWFLineStyle2
  715. self.start_caps_style = LineCapsStyle.ROUND
  716. self.end_caps_style = LineCapsStyle.ROUND
  717. self.joint_style = LineJointStyle.ROUND
  718. self.has_fill_flag = False
  719. self.no_hscale_flag = False
  720. self.no_vscale_flag = False
  721. self.pixelhinting_flag = False
  722. self.no_close = False
  723. self.miter_limit_factor = 3.0
  724. self.fill_type = None
  725. self.width = 1
  726. self.color = 0
  727. if not data is None:
  728. self.parse(data, level)
  729. def get_dependencies(self):
  730. return set()
  731. def parse(self, data, level=1):
  732. self.width = data.readUI16()
  733. self.color = data.readRGB() if level <= 2 else data.readRGBA()
  734. def __str__(self):
  735. s = "[SWFLineStyle] "
  736. s += "Color: %s, Width: %d" % (ColorUtils.to_rgb_string(self.color), self.width)
  737. return s
  738. class SWFLineStyle2(SWFLineStyle):
  739. def __init__(self, data=None, level=1):
  740. super(SWFLineStyle2, self).__init__(data, level)
  741. def parse(self, data, level=1):
  742. self.width = data.readUI16()
  743. self.start_caps_style = data.readUB(2)
  744. self.joint_style = data.readUB(2)
  745. self.has_fill_flag = (data.readUB(1) == 1)
  746. self.no_hscale_flag = (data.readUB(1) == 1)
  747. self.no_vscale_flag = (data.readUB(1) == 1)
  748. self.pixelhinting_flag = (data.readUB(1) == 1)
  749. data.readUB(5)
  750. self.no_close = (data.readUB(1) == 1)
  751. self.end_caps_style = data.readUB(2)
  752. if self.joint_style == LineJointStyle.MITER:
  753. self.miter_limit_factor = data.readFIXED8()
  754. if self.has_fill_flag:
  755. self.fill_type = data.readFILLSTYLE(level)
  756. else:
  757. self.color = data.readRGBA()
  758. def __str__(self):
  759. s = "[SWFLineStyle2] "
  760. s += "Width: %d, " % self.width
  761. s += "StartCapsStyle: %d, " % self.start_caps_style
  762. s += "JointStyle: %d, " % self.joint_style
  763. s += "HasFillFlag: %d, " % self.has_fill_flag
  764. s += "NoHscaleFlag: %d, " % self.no_hscale_flag
  765. s += "NoVscaleFlag: %d, " % self.no_vscale_flag
  766. s += "PixelhintingFlag: %d, " % self.pixelhinting_flag
  767. s += "NoClose: %d, " % self.no_close
  768. if self.joint_style:
  769. s += "MiterLimitFactor: %d" % self.miter_limit_factor
  770. if self.has_fill_flag:
  771. s += "FillType: %s, " % self.fill_type
  772. else:
  773. s += "Color: %s" % ColorUtils.to_rgb_string(self.color)
  774. return s
  775. class SWFMorphGradientRecord(_dumb_repr):
  776. def __init__(self, data):
  777. if not data is None:
  778. self.parse(data)
  779. def parse(self, data):
  780. self.startRatio = data.readUI8()
  781. self.startColor = data.readRGBA()
  782. self.endRatio = data.readUI8()
  783. self.endColor = data.readRGBA()
  784. class SWFMorphGradient(_dumb_repr):
  785. def __init__(self, data, level=1):
  786. self.records = []
  787. if not data is None:
  788. self.parse(data, level)
  789. def parse(self, data, level=1):
  790. self.records = []
  791. numGradients = data.readUI8()
  792. for i in range(0, numGradients):
  793. self.records.append(data.readMORPHGRADIENTRECORD())
  794. class SWFMorphFillStyle(_dumb_repr):
  795. def __init__(self, data, level=1):
  796. if not data is None:
  797. self.parse(data, level)
  798. def get_dependencies(self):
  799. return set([self.bitmapId]) if hasattr(self, 'bitmapId') else set()
  800. def parse(self, data, level=1):
  801. type = data.readUI8()
  802. if type == 0x0:
  803. self.startColor = data.readRGBA()
  804. self.endColor = data.readRGBA()
  805. elif type in [0x10, 0x12]:
  806. self.startGradientMatrix = data.readMATRIX()
  807. self.endGradientMatrix = data.readMATRIX()
  808. self.gradient = data.readMORPHGRADIENT(level)
  809. elif type in [0x40, 0x41, 0x42, 0x43]:
  810. self.bitmapId = data.readUI16()
  811. self.startBitmapMatrix = data.readMATRIX()
  812. self.endBitmapMatrix = data.readMATRIX()
  813. class SWFMorphLineStyle(_dumb_repr):
  814. def __init__(self, data, level=1):
  815. # Forward declaration of SWFMorphLineStyle2 properties
  816. self.startCapsStyle = LineCapsStyle.ROUND
  817. self.endCapsStyle = LineCapsStyle.ROUND
  818. self.jointStyle = LineJointStyle.ROUND
  819. self.hasFillFlag = False
  820. self.noHScaleFlag = False
  821. self.noVScaleFlag = False
  822. self.pixelHintingFlag = False
  823. self.noClose = False
  824. self.miterLimitFactor = 3
  825. self.fillType = None
  826. if not data is None:
  827. self.parse(data, level)
  828. def parse(self, data, level=1):
  829. self.startWidth = data.readUI16()
  830. self.endWidth = data.readUI16()
  831. self.startColor = data.readRGBA()
  832. self.endColor = data.readRGBA()
  833. class SWFMorphLineStyle2(SWFMorphLineStyle):
  834. def __init__(self, data, level=1):
  835. super(SWFMorphLineStyle2, self).__init__(data, level)
  836. def parse(self, data, level=1):
  837. self.startWidth = data.readUI16()
  838. self.endWidth = data.readUI16()
  839. self.startCapsStyle = data.readUB(2)
  840. self.jointStyle = data.readUB(2)
  841. self.hasFillFlag = (data.readUB(1) == 1)
  842. self.noHScaleFlag = (data.readUB(1) == 1)
  843. self.noVScaleFlag = (data.readUB(1) == 1)
  844. self.pixelHintingFlag = (data.readUB(1) == 1)
  845. reserved = data.readUB(5);
  846. self.noClose = (data.readUB(1) == 1)
  847. self.endCapsStyle = data.readUB(2)
  848. if self.jointStyle == LineJointStyle.MITER:
  849. self.miterLimitFactor = data.readFIXED8()
  850. if self.hasFillFlag:
  851. self.fillType = data.readMORPHFILLSTYLE(level)
  852. else:
  853. self.startColor = data.readRGBA()
  854. self.endColor = data.readRGBA()
  855. class SWFRecordHeader(_dumb_repr):
  856. def __init__(self, type, content_length, header_length):
  857. self.type = type
  858. self.content_length = content_length
  859. self.header_length = header_length
  860. @property
  861. def tag_length(self):
  862. return self.header_length + self.content_length
  863. class SWFRectangle(_dumb_repr):
  864. def __init__(self):
  865. self.xmin = self.xmax = self.ymin = self.ymax = 0
  866. def parse(self, s):
  867. s.reset_bits_pending()
  868. bits = s.readUB(5)
  869. self.xmin = s.readSB(bits)
  870. self.xmax = s.readSB(bits)
  871. self.ymin = s.readSB(bits)
  872. self.ymax = s.readSB(bits)
  873. @property
  874. def dimensions(self):
  875. """
  876. Returns dimensions as (x, y) tuple.
  877. """
  878. return (self.xmax - self.xmin, self.ymax - self.ymin)
  879. def __str__(self):
  880. return "[xmin: %d xmax: %d ymin: %d ymax: %d]" % (self.xmin/20, self.xmax/20, self.ymin/20, self.ymax/20)
  881. class SWFColorTransform(_dumb_repr):
  882. def __init__(self, data=None):
  883. if not data is None:
  884. self.parse(data)
  885. def parse(self, data):
  886. data.reset_bits_pending()
  887. self.hasAddTerms = (data.readUB(1) == 1)
  888. self.hasMultTerms = (data.readUB(1) == 1)
  889. bits = data.readUB(4)
  890. self.rMult = 1
  891. self.gMult = 1
  892. self.bMult = 1
  893. if self.hasMultTerms:
  894. self.rMult = data.readSB(bits)
  895. self.gMult = data.readSB(bits)
  896. self.bMult = data.readSB(bits)
  897. self.rAdd = 0
  898. self.gAdd = 0
  899. self.bAdd = 0
  900. if self.hasAddTerms:
  901. self.rAdd = data.readSB(bits)
  902. self.gAdd = data.readSB(bits)
  903. self.bAdd = data.readSB(bits)
  904. @property
  905. def matrix(self):
  906. return [
  907. self.rMult / 256.0, 0.0, 0.0, 0.0, self.rAdd / 256.0,
  908. 0.0, self.gMult / 256.0, 0.0, 0.0, self.gAdd / 256.0,
  909. 0.0, 0.0, self.bMult / 256.0, 0.0, self.bAdd / 256.0,
  910. 0.0, 0.0, 0.0, 1.0, 1.0
  911. ]
  912. def __str__(self):
  913. return "[%d %d %d %d %d %d]" % \
  914. (self.rMult, self.gMult, self.bMult, self.rAdd, self.gAdd, self.bAdd)
  915. class SWFColorTransformWithAlpha(SWFColorTransform):
  916. def __init__(self, data=None):
  917. super(SWFColorTransformWithAlpha, self).__init__(data)
  918. def parse(self, data):
  919. data.reset_bits_pending()
  920. self.hasAddTerms = (data.readUB(1) == 1)
  921. self.hasMultTerms = (data.readUB(1) == 1)
  922. bits = data.readUB(4)
  923. self.rMult = 1
  924. self.gMult = 1
  925. self.bMult = 1
  926. self.aMult = 1
  927. if self.hasMultTerms:
  928. self.rMult = data.readSB(bits)
  929. self.gMult = data.readSB(bits)
  930. self.bMult = data.readSB(bits)
  931. self.aMult = data.readSB(bits)
  932. self.rAdd = 0
  933. self.gAdd = 0
  934. self.bAdd = 0
  935. self.aAdd = 0
  936. if self.hasAddTerms:
  937. self.rAdd = data.readSB(bits)
  938. self.gAdd = data.readSB(bits)
  939. self.bAdd = data.readSB(bits)
  940. self.aAdd = data.readSB(bits)
  941. @property
  942. def matrix(self):
  943. '''
  944. Gets the matrix as a 20 item list
  945. '''
  946. return [
  947. self.rMult / 256.0, 0.0, 0.0, 0.0, self.rAdd / 256.0,
  948. 0.0, self.gMult / 256.0, 0.0, 0.0, self.gAdd / 256.0,
  949. 0.0, 0.0, self.bMult / 256.0, 0.0, self.bAdd / 256.0,
  950. 0.0, 0.0, 0.0, self.aMult / 256.0, self.aAdd / 256.0
  951. ]
  952. def __str__(self):
  953. return "[%d %d %d %d %d %d %d %d]" % \
  954. (self.rMult, self.gMult, self.bMult, self.aMult, self.rAdd, self.gAdd, self.bAdd, self.aAdd)
  955. class SWFFrameLabel(_dumb_repr):
  956. def __init__(self, frameNumber, name):
  957. self.frameNumber = frameNumber
  958. self.name = name
  959. def __str__(self):
  960. return "Frame: %d, Name: %s" % (self.frameNumber, self.name)
  961. class SWFScene(_dumb_repr):
  962. def __init__(self, offset, name):
  963. self.offset = offset
  964. self.name = name
  965. def __str__(self):
  966. return "Scene: %d, Name: '%s'" % (self.offset, self.name)
  967. class SWFSymbol(_dumb_repr):
  968. def __init__(self, data=None):
  969. if not data is None:
  970. self.parse(data)
  971. def parse(self, data):
  972. self.tagId = data.readUI16()
  973. self.name = data.readString()
  974. def __str__(self):
  975. return "ID %d, Name: %s" % (self.tagId, self.name)
  976. class SWFGlyphEntry(_dumb_repr):
  977. def __init__(self, data=None, glyphBits=0, advanceBits=0):
  978. if not data is None:
  979. self.parse(data, glyphBits, advanceBits)
  980. def parse(self, data, glyphBits, advanceBits):
  981. # GLYPHENTRYs are not byte aligned
  982. self.index = data.readUB(glyphBits)
  983. self.advance = data.readSB(advanceBits)
  984. def __str__(self):
  985. return "Index: %d, Advance: %d" % (self.index, self.advance)
  986. class SWFKerningRecord(_dumb_repr):
  987. def __init__(self, data=None, wideCodes=False):
  988. if not data is None:
  989. self.parse(data, wideCodes)
  990. def parse(self, data, wideCodes):
  991. self.code1 = data.readUI16() if wideCodes else data.readUI8()
  992. self.code2 = data.readUI16() if wideCodes else data.readUI8()
  993. self.adjustment = data.readSI16()
  994. def __str__(self):
  995. return "Code1: %d, Code2: %d, Adjustment: %d" % (self.code1, self.code2, self.adjustment)
  996. class SWFTextRecord(_dumb_repr):
  997. def __init__(self, data=None, glyphBits=0, advanceBits=0, previousRecord=None, level=1):
  998. self.hasFont = False
  999. self.hasColor = False
  1000. self.hasYOffset = False
  1001. self.hasXOffset = False
  1002. self.fontId = -1
  1003. self.textColor = 0
  1004. self.xOffset = 0
  1005. self.yOffset = 0
  1006. self.textHeight = 12
  1007. self.glyphEntries = []
  1008. if not data is None:
  1009. self.parse(data, glyphBits, advanceBits, previousRecord, level)
  1010. def get_dependencies(self):
  1011. return set([self.fontId]) if self.hasFont else set()
  1012. def parse(self, data, glyphBits, advanceBits, previousRecord=None, level=1):
  1013. self.glyphEntries = []
  1014. styles = data.readUI8()
  1015. self.type = styles >> 7
  1016. self.hasFont = ((styles & 0x08) != 0)
  1017. self.hasColor = ((styles & 0x04) != 0)
  1018. self.hasYOffset = ((styles & 0x02) != 0)
  1019. self.hasXOffset = ((styles & 0x01) != 0)
  1020. if self.hasFont:
  1021. self.fontId = data.readUI16()
  1022. elif not previousRecord is None:
  1023. self.fontId = previousRecord.fontId
  1024. if self.hasColor:
  1025. self.textColor = data.readRGB() if level < 2 else data.readRGBA()
  1026. elif not previousRecord is None:
  1027. self.textColor = previousRecord.textColor
  1028. if self.hasXOffset:
  1029. self.xOffset = data.readSI16();
  1030. elif not previousRecord is None:
  1031. self.xOffset = previousRecord.xOffset
  1032. if self.hasYOffset:
  1033. self.yOffset = data.readSI16();
  1034. elif not previousRecord is None:
  1035. self.yOffset = previousRecord.yOffset
  1036. if self.hasFont:
  1037. self.textHeight = data.readUI16()
  1038. elif not previousRecord is None:
  1039. self.textHeight = previousRecord.textHeight
  1040. glyphCount = data.readUI8()
  1041. for i in range(0, glyphCount):
  1042. self.glyphEntries.append(data.readGLYPHENTRY(glyphBits, advanceBits))
  1043. def __str__(self):
  1044. return "[SWFTextRecord]"
  1045. class SWFClipActions(_dumb_repr):
  1046. def __init__(self, data=None, version=0):
  1047. self.eventFlags = None
  1048. self.records = []
  1049. if not data is None:
  1050. self.parse(data, version)
  1051. def parse(self, data, version):
  1052. data.readUI16() # reserved, always 0
  1053. self.eventFlags = data.readCLIPEVENTFLAGS(version)
  1054. self.records = []
  1055. record = data.readCLIPACTIONRECORD(version)
  1056. while not record is None:
  1057. self.records.append(record)
  1058. record = data.readCLIPACTIONRECORD(version)
  1059. def __str__(self):
  1060. return "[SWFClipActions]"
  1061. class SWFClipActionRecord(_dumb_repr):
  1062. def __init__(self, data=None, version=0):
  1063. self.eventFlags = None
  1064. self.keyCode = 0
  1065. self.actions = []
  1066. if not data is None:
  1067. self.parse(data, version)
  1068. def parse(self, data, version):
  1069. self.actions = []
  1070. self.eventFlags = data.readCLIPEVENTFLAGS(version)
  1071. data.readUI32() # actionRecordSize, not needed here
  1072. if self.eventFlags.keyPressEvent:
  1073. self.keyCode = data.readUI8()
  1074. action = data.readACTIONRECORD()
  1075. while not action is None:
  1076. self.actions.append(action)
  1077. action = data.readACTIONRECORD()
  1078. def __str__(self):
  1079. return "[SWFClipActionRecord]"
  1080. class SWFClipEventFlags(_dumb_repr):
  1081. keyUpEvent = False
  1082. keyDownEvent = False
  1083. mouseUpEvent = False
  1084. mouseDownEvent = False
  1085. mouseMoveEvent = False
  1086. unloadEvent = False
  1087. enterFrameEvent = False
  1088. loadEvent = False
  1089. dragOverEvent = False # SWF6
  1090. rollOutEvent = False # SWF6
  1091. rollOverEvent = False # SWF6
  1092. releaseOutsideEvent = False # SWF6
  1093. releaseEvent = False # SWF6
  1094. pressEvent = False # SWF6
  1095. initializeEvent = False # SWF6
  1096. dataEvent = False
  1097. constructEvent = False # SWF7
  1098. keyPressEvent = False # SWF6
  1099. dragOutEvent = False # SWF6
  1100. def __init__(self, data=None, version=0):
  1101. if not data is None:
  1102. self.parse(data, version)
  1103. def parse(self, data, version):
  1104. flags1 = data.readUI8();
  1105. self.keyUpEvent = ((flags1 & 0x80) != 0)
  1106. self.keyDownEvent = ((flags1 & 0x40) != 0)
  1107. self.mouseUpEvent = ((flags1 & 0x20) != 0)
  1108. self.mouseDownEvent = ((flags1 & 0x10) != 0)
  1109. self.mouseMoveEvent = ((flags1 & 0x08) != 0)
  1110. self.unloadEvent = ((flags1 & 0x04) != 0)
  1111. self.enterFrameEvent = ((flags1 & 0x02) != 0)
  1112. self.loadEvent = ((flags1 & 0x01) != 0)
  1113. flags2 = data.readUI8()
  1114. self.dragOverEvent = ((flags2 & 0x80) != 0)
  1115. self.rollOutEvent = ((flags2 & 0x40) != 0)
  1116. self.rollOverEvent = ((flags2 & 0x20) != 0)
  1117. self.releaseOutsideEvent = ((flags2 & 0x10) != 0)
  1118. self.releaseEvent = ((flags2 & 0x08) != 0)
  1119. self.pressEvent = ((flags2 & 0x04) != 0)
  1120. self.initializeEvent = ((flags2 & 0x02) != 0)
  1121. self.dataEvent = ((flags2 & 0x01) != 0)
  1122. if version >= 6:
  1123. flags3 = data.readUI8()
  1124. self.constructEvent = ((flags3 & 0x04) != 0)
  1125. self.keyPressEvent = ((flags3 & 0x02) != 0)
  1126. self.dragOutEvent = ((flags3 & 0x01) != 0)
  1127. data.readUI8() # reserved, always 0
  1128. def __str__(self):
  1129. return "[SWFClipEventFlags]"
  1130. class SWFZoneData(_dumb_repr):
  1131. def __init__(self, data=None):
  1132. if not data is None:
  1133. self.parse(data)
  1134. def parse(self, data):
  1135. self.alignmentCoordinate = data.readFLOAT16()
  1136. self.zoneRange = data.readFLOAT16()
  1137. def __str__(self):
  1138. return "[SWFZoneData]"
  1139. class SWFZoneRecord(_dumb_repr):
  1140. def __init__(self, data=None):
  1141. if not data is None:
  1142. self.parse(data)
  1143. def parse(self, data):
  1144. self.zoneData = []
  1145. numZoneData = data.readUI8()
  1146. for i in range(0, numZoneData):
  1147. self.zoneData.append(data.readZONEDATA())
  1148. mask = data.readUI8()
  1149. self.maskX = ((mask & 0x01) != 0)
  1150. self.maskY = ((mask & 0x02) != 0)
  1151. def __str__(self):
  1152. return "[SWFZoneRecord]"
  1153. class SWFSoundInfo(_dumb_repr):
  1154. def __init__(self, data=None):
  1155. if not data is None:
  1156. self.parse(data)
  1157. def parse(self, data):
  1158. reserved = data.readUB(2)
  1159. assert reserved == 0
  1160. self.syncStop = data.readUB(1) == 1
  1161. self.syncNoMultiple = data.readUB(1) == 1
  1162. self.hasEnvelope = data.readUB(1) == 1
  1163. self.hasLoops = data.readUB(1) == 1
  1164. self.hasOutPoint = data.readUB(1) == 1
  1165. self.hasInPoint = data.readUB(1) == 1
  1166. self.inPoint = data.readUI32() if self.hasInPoint else None
  1167. self.outPoint = data.readUI32() if self.hasOutPoint else None
  1168. self.loopCount = data.readUI16() if self.hasLoops else None
  1169. self.envPointCount = data.readUI8() if self.hasEnvelope else None
  1170. self.envelopePoints = [data.readSOUNDENVELOPE() for x in xrange(self.envPointCount)] if self.hasEnvelope else None
  1171. def __str__(self):
  1172. return "[SWFSoundInfo]"
  1173. class SWFSoundEnvelope(_dumb_repr):
  1174. def __init__(self, data=None):
  1175. if not data is None:
  1176. self.parse(data)
  1177. def parse(self, data):
  1178. self.position = data.readUI32()
  1179. self.leftLevel = data.readUI16()
  1180. self.rightLevel = data.readUI16()
  1181. def __str__(self):
  1182. return "[SWFSoundEnvelope]"
  1183. class SWFButtonRecord(_dumb_repr):
  1184. def __init__(self, version, data=None):
  1185. # version is 1 for DefineButton, 2 for DefineButton2, etc
  1186. if not data is None:
  1187. self.parse(data, version)
  1188. def get_dependencies(self):
  1189. return set([self.characterId]) if self.valid else set()
  1190. def parse(self, data, version):
  1191. reserved0 = data.readUB(2)
  1192. self.hasBlendMode = data.readUB(1) == 1
  1193. self.hasFilterList = data.readUB(1) == 1
  1194. self.stateHitTest = data.readUB(1) == 1
  1195. self.stateDown = data.readUB(1) == 1
  1196. self.stateOver = data.readUB(1) == 1
  1197. self.stateUp = data.readUB(1) == 1
  1198. self.valid = reserved0 or self.hasBlendMode or \
  1199. self.hasFilterList or self.stateHitTest or \
  1200. self.stateDown or self.stateOver or self.stateUp
  1201. if not self.valid:
  1202. return
  1203. self.characterId = data.readUI16()
  1204. self.placeDepth = data.readUI16()
  1205. self.placeMatrix = data.readMATRIX()
  1206. if version == 2:
  1207. self.colorTransform = data.readCXFORMWITHALPHA()
  1208. self.filterList = data.readFILTERLIST() if self.hasFilterList else None
  1209. self.blendMode = data.readUI8() if self.hasBlendMode else 0
  1210. def __str__(self):
  1211. return "[SWFButtonRecord]"
  1212. def __repr__(self):
  1213. return "[SWFButtonRecord %r]" % self.__dict__
  1214. class SWFButtonCondAction(_dumb_repr):
  1215. def __init__(self, data=None):
  1216. if not data is None:
  1217. self.parse(data)
  1218. def parse(self, data):
  1219. self.idleToOverDown = data.readUB(1) == 1
  1220. self.outDownToIdle = data.readUB(1) == 1
  1221. self.outDownToOverDown = data.readUB(1) == 1
  1222. self.overDownToOutDown = data.readUB(1) == 1
  1223. self.overDownToOverUp = data.readUB(1) == 1
  1224. self.overUpToOverDown = data.readUB(1) == 1
  1225. self.overUpToIdle = data.readUB(1) == 1
  1226. self.idleToOverUp = data.readUB(1) == 1
  1227. self.keyPress = data.readUB(7)
  1228. self.overDownToIdle = data.readUB(1) == 1
  1229. self.actions = data.readACTIONRECORDs()
  1230. def __str__(self):
  1231. return "[SWFButtonCondAction]"
  1232. class SWFExport(_dumb_repr):
  1233. def __init__(self, data=None):
  1234. if not data is None:
  1235. self.parse(data)
  1236. def get_dependencies(self):
  1237. return set([self.characterId])
  1238. def parse(self, data):
  1239. self.characterId = data.readUI16()
  1240. self.characterName = data.readString()
  1241. def __str__(self):
  1242. return "[SWFExport %d as %r]" % (self.characterId, self.characterName)