123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437 |
- from .consts import *
- from .utils import *
- class _dumb_repr(object):
- def __repr__(self):
- return '<%s %r>' % (self.__class__.__name__, self.__dict__)
- class SWFRawTag(_dumb_repr):
- def __init__(self, s=None):
- if not s is None:
- self.parse(s)
- def parse(self, s):
- pos = s.tell()
- self.header = s.readtag_header()
- self.pos_content = s.tell()
- s.f.seek(pos)
- #self.bytes = s.f.read(self.header.tag_length())
- #s.f.seek(self.pos_content)
- class SWFStraightEdge(_dumb_repr):
- def __init__(self, start, to, line_style_idx, fill_style_idx):
- self.start = start
- self.to = to
- self.line_style_idx = line_style_idx
- self.fill_style_idx = fill_style_idx
- def reverse_with_new_fillstyle(self, new_fill_idx):
- return SWFStraightEdge(self.to, self.start, self.line_style_idx, new_fill_idx)
- class SWFCurvedEdge(SWFStraightEdge):
- def __init__(self, start, control, to, line_style_idx, fill_style_idx):
- super(SWFCurvedEdge, self).__init__(start, to, line_style_idx, fill_style_idx)
- self.control = control
- def reverse_with_new_fillstyle(self, new_fill_idx):
- return SWFCurvedEdge(self.to, self.control, self.start, self.line_style_idx, new_fill_idx)
- class SWFShape(_dumb_repr):
- def __init__(self, data=None, level=1, unit_divisor=20.0):
- self._records = []
- self._fillStyles = []
- self._lineStyles = []
- self._postLineStyles = {}
- self._edgeMapsCreated = False
- self.unit_divisor = unit_divisor
- self.fill_edge_maps = []
- self.line_edge_maps = []
- self.current_fill_edge_map = {}
- self.current_line_edge_map = {}
- self.num_groups = 0
- self.coord_map = {}
- if not data is None:
- self.parse(data, level)
- def get_dependencies(self):
- s = set()
- for x in self._fillStyles:
- s.update(x.get_dependencies())
- for x in self._lineStyles:
- s.update(x.get_dependencies())
- return s
- def parse(self, data, level=1):
- data.reset_bits_pending()
- fillbits = data.readUB(4)
- linebits = data.readUB(4)
- self.read_shape_records(data, fillbits, linebits, level)
- def export(self, handler=None):
- self._create_edge_maps()
- if handler is None:
- from export import SVGShapeExporter
- handler = SVGShapeExporter()
- handler.begin_shape()
- for i in range(0, self.num_groups):
- self._export_fill_path(handler, i)
- self._export_line_path(handler, i)
- handler.end_shape()
- return handler
- @property
- def records(self):
- return self._records
- def read_shape_records(self, data, fill_bits, line_bits, level=1):
- shape_record = None
- record_id = 0
- while type(shape_record) != SWFShapeRecordEnd:
- # The SWF10 spec says that shape records are byte aligned.
- # In reality they seem not to be?
- # bitsPending = 0;
- edge_record = (data.readUB(1) == 1)
- if edge_record:
- straight_flag = (data.readUB(1) == 1)
- num_bits = data.readUB(4) + 2
- if straight_flag:
- shape_record = data.readSTRAIGHTEDGERECORD(num_bits)
- else:
- shape_record = data.readCURVEDEDGERECORD(num_bits)
- else:
- states= data.readUB(5)
- if states == 0:
- shape_record = SWFShapeRecordEnd()
- else:
- style_change_record = data.readSTYLECHANGERECORD(states, fill_bits, line_bits, level)
- if style_change_record.state_new_styles:
- fill_bits = style_change_record.num_fillbits
- line_bits = style_change_record.num_linebits
- shape_record = style_change_record
- shape_record.record_id = record_id
- self._records.append(shape_record)
- record_id += 1
- #print shape_record.tostring()
- def _create_edge_maps(self):
- if self._edgeMapsCreated:
- return
- xPos = 0
- yPos = 0
- sub_path = []
- fs_offset = 0
- ls_offset = 0
- curr_fs_idx0 = 0
- curr_fs_idx1 = 0
- curr_ls_idx = 0
- self.fill_edge_maps = []
- self.line_edge_maps = []
- self.current_fill_edge_map = {}
- self.current_line_edge_map = {}
- self.num_groups = 0
- for i in range(0, len(self._records)):
- rec = self._records[i]
- if rec.type == SWFShapeRecord.TYPE_STYLECHANGE:
- if rec.state_line_style or rec.state_fill_style0 or rec.state_fill_style1:
- if len(sub_path):
- self._process_sub_path(sub_path, curr_ls_idx, curr_fs_idx0, curr_fs_idx1, rec.record_id)
- sub_path = []
- if rec.state_new_styles:
- fs_offset = len(self._fillStyles)
- ls_offset = len(self._lineStyles)
- self._append_to(self._fillStyles, rec.fill_styles)
- self._append_to(self._lineStyles, rec.line_styles)
- if rec.state_line_style and rec.state_fill_style0 and rec.state_fill_style1 and \
- rec.line_style == 0 and rec.fill_style0 == 0 and rec.fill_style1 == 0:
- # new group (probably)
- self._clean_edge_map(self.current_fill_edge_map)
- self._clean_edge_map(self.current_line_edge_map)
- self.fill_edge_maps.append(self.current_fill_edge_map)
- self.line_edge_maps.append(self.current_line_edge_map)
- self.current_fill_edge_map = {}
- self.current_line_edge_map = {}
- self.num_groups += 1
- curr_fs_idx0 = 0
- curr_fs_idx1 = 0
- curr_ls_idx = 0
- else:
- if rec.state_line_style:
- curr_ls_idx = rec.line_style
- if curr_ls_idx > 0:
- curr_ls_idx += ls_offset
- if rec.state_fill_style0:
- curr_fs_idx0 = rec.fill_style0
- if curr_fs_idx0 > 0:
- curr_fs_idx0 += fs_offset
- if rec.state_fill_style1:
- curr_fs_idx1 = rec.fill_style1
- if curr_fs_idx1 > 0:
- curr_fs_idx1 += fs_offset
- if rec.state_moveto:
- xPos = rec.move_deltaX
- yPos = rec.move_deltaY
- elif rec.type == SWFShapeRecord.TYPE_STRAIGHTEDGE:
- start = [NumberUtils.round_pixels_400(xPos), NumberUtils.round_pixels_400(yPos)]
- if rec.general_line_flag:
- xPos += rec.deltaX
- yPos += rec.deltaY
- else:
- if rec.vert_line_flag:
- yPos += rec.deltaY
- else:
- xPos += rec.deltaX
- to = [NumberUtils.round_pixels_400(xPos), NumberUtils.round_pixels_400(yPos)]
- sub_path.append(SWFStraightEdge(start, to, curr_ls_idx, curr_fs_idx1))
- elif rec.type == SWFShapeRecord.TYPE_CURVEDEDGE:
- start = [NumberUtils.round_pixels_400(xPos), NumberUtils.round_pixels_400(yPos)]
- xPosControl = xPos + rec.control_deltaX
- yPosControl = yPos + rec.control_deltaY
- xPos = xPosControl + rec.anchor_deltaX
- yPos = yPosControl + rec.anchor_deltaY
- control = [xPosControl, yPosControl]
- to = [NumberUtils.round_pixels_400(xPos), NumberUtils.round_pixels_400(yPos)]
- sub_path.append(SWFCurvedEdge(start, control, to, curr_ls_idx, curr_fs_idx1))
- elif rec.type == SWFShapeRecord.TYPE_END:
- # We're done. Process the last subpath, if any
- if len(sub_path) > 0:
- self._process_sub_path(sub_path, curr_ls_idx, curr_fs_idx0, curr_fs_idx1, rec.record_id)
- self._clean_edge_map(self.current_fill_edge_map)
- self._clean_edge_map(self.current_line_edge_map)
- self.fill_edge_maps.append(self.current_fill_edge_map)
- self.line_edge_maps.append(self.current_line_edge_map)
- self.current_fill_edge_map = {}
- self.current_line_edge_map = {}
- self.num_groups += 1
- curr_fs_idx0 = 0
- curr_fs_idx1 = 0
- curr_ls_idx = 0
- self._edgeMapsCreated = True
- def _process_sub_path(self, sub_path, linestyle_idx, fillstyle_idx0, fillstyle_idx1, record_id=-1):
- path = None
- if fillstyle_idx0 != 0:
- if not fillstyle_idx0 in self.current_fill_edge_map:
- path = self.current_fill_edge_map[fillstyle_idx0] = []
- else:
- path = self.current_fill_edge_map[fillstyle_idx0]
- for j in range(len(sub_path) - 1, -1, -1):
- path.append(sub_path[j].reverse_with_new_fillstyle(fillstyle_idx0))
- if fillstyle_idx1 != 0:
- if not fillstyle_idx1 in self.current_fill_edge_map:
- path = self.current_fill_edge_map[fillstyle_idx1] = []
- else:
- path = self.current_fill_edge_map[fillstyle_idx1]
- self._append_to(path, sub_path)
- if linestyle_idx != 0:
- if not linestyle_idx in self.current_line_edge_map:
- path = self.current_line_edge_map[linestyle_idx] = []
- else:
- path = self.current_line_edge_map[linestyle_idx]
- self._append_to(path, sub_path)
- def _clean_edge_map(self, edge_map):
- for style_idx in edge_map:
- sub_path = edge_map[style_idx] if style_idx in edge_map else None
- if sub_path is not None and len(sub_path) > 0:
- tmp_path = []
- prev_edge = None
- self._create_coord_map(sub_path)
- while len(sub_path) > 0:
- idx = 0
- while idx < len(sub_path):
- if prev_edge is None or self._equal_point(prev_edge.to, sub_path[idx].start):
- edge = sub_path[idx]
- del sub_path[idx]
- tmp_path.append(edge)
- self._remove_edge_from_coord_map(edge)
- prev_edge = edge
- else:
- edge = self._find_next_edge_in_coord_map(prev_edge)
- if not edge is None:
- idx = sub_path.index(edge)
- else:
- idx = 0
- prev_edge = None
- edge_map[style_idx] = tmp_path
- def _equal_point(self, a, b, tol=0.001):
- return (a[0] > b[0]-tol and a[0] < b[0]+tol and a[1] > b[1]-tol and a[1] < b[1]+tol)
- def _find_next_edge_in_coord_map(self, edge):
- key = "%0.4f_%0.4f" % (edge.to[0], edge.to[1])
- if key in self.coord_map and len(self.coord_map[key]) > 0:
- return self.coord_map[key][0]
- else:
- return None
- def _create_coord_map(self, path):
- self.coord_map = {}
- for i in range(0, len(path)):
- start = path[i].start
- key = "%0.4f_%0.4f" % (start[0], start[1])
- coord_map_array = self.coord_map[key] if key in self.coord_map else None
- if coord_map_array is None:
- self.coord_map[key] = [path[i]]
- else:
- self.coord_map[key].append(path[i])
- def _remove_edge_from_coord_map(self, edge):
- key = "%0.4f_%0.4f" % (edge.start[0], edge.start[1])
- if key in self.coord_map:
- coord_map_array = self.coord_map[key]
- if len(coord_map_array) == 1:
- del self.coord_map[key]
- else:
- try:
- idx = coord_map_array.index(edge)
- del coord_map_array[idx]
- except:
- pass
- def _create_path_from_edge_map(self, edge_map):
- new_path = []
- style_ids = []
- for style_id in edge_map:
- style_ids.append(int(style_id))
- style_ids = sorted(style_ids)
- for i in range(0, len(style_ids)):
- self._append_to(new_path, edge_map[style_ids[i]])
- return new_path
- def _export_fill_path(self, handler, group_index):
- path = self._create_path_from_edge_map(self.fill_edge_maps[group_index])
- pos = [100000000, 100000000]
- u = 1.0 / self.unit_divisor
- fill_style_idx = 10000000
- if len(path) < 1:
- return
- handler.begin_fills()
- for i in range(0, len(path)):
- e = path[i]
- if fill_style_idx != e.fill_style_idx:
- fill_style_idx = e.fill_style_idx
- pos = [100000000, 100000000]
- try:
- fill_style = self._fillStyles[fill_style_idx - 1] if fill_style_idx > 0 else None
- if fill_style.type == 0x0:
- # solid fill
- handler.begin_fill(
- ColorUtils.rgb(fill_style.rgb),
- ColorUtils.alpha(fill_style.rgb))
- elif fill_style.type in [0x10, 0x12, 0x13]:
- # gradient fill
- colors = []
- ratios = []
- alphas = []
- for j in range(0, len(fill_style.gradient.records)):
- gr = fill_style.gradient.records[j]
- colors.append(ColorUtils.rgb(gr.color))
- ratios.append(gr.ratio)
- alphas.append(ColorUtils.alpha(gr.color))
- handler.begin_gradient_fill(
- GradientType.LINEAR if fill_style.type == 0x10 else GradientType.RADIAL,
- colors, alphas, ratios,
- fill_style.gradient_matrix,
- fill_style.gradient.spreadmethod,
- fill_style.gradient.interpolation_mode,
- fill_style.gradient.focal_point
- )
- elif fill_style.type in [0x40, 0x41, 0x42, 0x43]:
- # bitmap fill
- handler.begin_bitmap_fill(
- fill_style.bitmap_id,
- fill_style.bitmap_matrix,
- (fill_style.type == 0x40 or fill_style.type == 0x42),
- (fill_style.type == 0x40 or fill_style.type == 0x41)
- )
- pass
- except:
- # Font shapes define no fillstyles per se, but do reference fillstyle index 1,
- # which represents the font color. We just report solid black in this case.
- handler.begin_fill(0)
- if not self._equal_point(pos, e.start):
- handler.move_to(e.start[0] * u, e.start[1] * u)
- if type(e) is SWFCurvedEdge:
- handler.curve_to(e.control[0] * u, e.control[1] * u, e.to[0] * u, e.to[1] * u)
- else:
- handler.line_to(e.to[0] * u, e.to[1] * u)
- pos = e.to
- handler.end_fill()
- handler.end_fills()
- def _export_line_path(self, handler, group_index):
- path = self._create_path_from_edge_map(self.line_edge_maps[group_index])
- pos = [100000000, 100000000]
- u = 1.0 / self.unit_divisor
- line_style_idx = 10000000
- line_style = None
- if len(path) < 1:
- return
- handler.begin_lines()
- for i in range(0, len(path)):
- e = path[i]
- if line_style_idx != e.line_style_idx:
- line_style_idx = e.line_style_idx
- pos = [100000000, 100000000]
- try:
- line_style = self._lineStyles[line_style_idx - 1]
- except:
- line_style = None
- if line_style is not None:
- scale_mode = LineScaleMode.NORMAL
- if line_style.no_hscale_flag and line_style.no_vscale_flag:
- scale_mode = LineScaleMode.NONE
- elif line_style.no_hscale_flag:
- scale_mode = LineScaleMode.HORIZONTAL
- elif line_style.no_hscale_flag:
- scale_mode = LineScaleMode.VERTICAL
- if not line_style.has_fill_flag:
- handler.line_style(
- line_style.width / 20.0,
- ColorUtils.rgb(line_style.color),
- ColorUtils.alpha(line_style.color),
- line_style.pixelhinting_flag,
- scale_mode,
- line_style.start_caps_style,
- line_style.end_caps_style,
- line_style.joint_style,
- line_style.miter_limit_factor)
- else:
- fill_style = line_style.fill_type
- if fill_style.type in [0x10, 0x12, 0x13]:
- # gradient fill
- colors = []
- ratios = []
- alphas = []
- for j in range(0, len(fill_style.gradient.records)):
- gr = fill_style.gradient.records[j]
- colors.append(ColorUtils.rgb(gr.color))
- ratios.append(gr.ratio)
- alphas.append(ColorUtils.alpha(gr.color))
- handler.line_gradient_style(
- line_style.width / 20.0,
- line_style.pixelhinting_flag,
- scale_mode,
- line_style.start_caps_style,
- line_style.end_caps_style,
- line_style.joint_style,
- line_style.miter_limit_factor,
- GradientType.LINEAR if fill_style.type == 0x10 else GradientType.RADIAL,
- colors, alphas, ratios,
- fill_style.gradient_matrix,
- fill_style.gradient.spreadmethod,
- fill_style.gradient.interpolation_mode,
- fill_style.gradient.focal_point
- )
- elif fill_style.type in [0x40, 0x41, 0x42]:
- handler.line_bitmap_style(
- line_style.width / 20.0,
- line_style.pixelhinting_flag,
- scale_mode,
- line_style.start_caps_style,
- line_style.end_caps_style,
- line_style.joint_style,
- line_style.miter_limit_factor,
- fill_style.bitmap_id, fill_style.bitmap_matrix,
- (fill_style.type == 0x40 or fill_style.type == 0x42),
- (fill_style.type == 0x40 or fill_style.type == 0x41)
- )
- else:
- # we should never get here
- handler.line_style(0)
- if not self._equal_point(pos, e.start):
- handler.move_to(e.start[0] * u, e.start[1] * u)
- if type(e) is SWFCurvedEdge:
- handler.curve_to(e.control[0] * u, e.control[1] * u, e.to[0] * u, e.to[1] * u)
- else:
- handler.line_to(e.to[0] * u, e.to[1] * u)
- pos = e.to
- handler.end_lines()
- def _append_to(self, v1, v2):
- for i in range(0, len(v2)):
- v1.append(v2[i])
- def __str__(self):
- return "[SWFShape]"
- class SWFShapeWithStyle(SWFShape):
- def __init__(self, data, level, unit_divisor):
- self._initialFillStyles = []
- self._initialLineStyles = []
- super(SWFShapeWithStyle, self).__init__(data, level, unit_divisor)
- def export(self, handler=None):
- self._fillStyles.extend(self._initialFillStyles)
- self._lineStyles.extend(self._initialLineStyles)
- return super(SWFShapeWithStyle, self).export(handler)
- def get_dependencies(self):
- s = set()
- for x in self._fillStyles + self._initialFillStyles:
- s.update(x.get_dependencies())
- for x in self._lineStyles + self._initialLineStyles:
- s.update(x.get_dependencies())
- return s
- def parse(self, data, level=1):
- data.reset_bits_pending()
- num_fillstyles = self.readstyle_array_length(data, level)
- for i in range(0, num_fillstyles):
- self._initialFillStyles.append(data.readFILLSTYLE(level))
- num_linestyles = self.readstyle_array_length(data, level)
- for i in range(0, num_linestyles):
- if level <= 3:
- self._initialLineStyles.append(data.readLINESTYLE(level))
- else:
- self._initialLineStyles.append(data.readLINESTYLE2(level))
- num_fillbits = data.readUB(4)
- num_linebits = data.readUB(4)
- data.reset_bits_pending()
- self.read_shape_records(data, num_fillbits, num_linebits, level)
- def readstyle_array_length(self, data, level=1):
- length = data.readUI8()
- if level >= 2 and length == 0xff:
- length = data.readUI16()
- return length
- def __str__(self):
- s = " FillStyles:\n" if len(self._fillStyles) > 0 else ""
- for i in range(0, len(self._initialFillStyles)):
- s += " %d:%s\n" % (i+1, self._initialFillStyles[i].__str__())
- if len(self._initialLineStyles) > 0:
- s += " LineStyles:\n"
- for i in range(0, len(self._initialLineStyles)):
- s += " %d:%s\n" % (i+1, self._initialLineStyles[i].__str__())
- for record in self._records:
- s += record.__str__() + '\n'
- return s.rstrip() + super(SWFShapeWithStyle, self).__str__()
- class SWFShapeRecord(_dumb_repr):
- TYPE_UNKNOWN = 0
- TYPE_END = 1
- TYPE_STYLECHANGE = 2
- TYPE_STRAIGHTEDGE = 3
- TYPE_CURVEDEDGE = 4
- record_id = -1
- def __init__(self, data=None, level=1):
- if not data is None:
- self.parse(data, level)
- @property
- def is_edge_record(self):
- return (self.type == SWFShapeRecord.TYPE_STRAIGHTEDGE or
- self.type == SWFShapeRecord.TYPE_CURVEDEDGE)
- def parse(self, data, level=1):
- pass
- @property
- def type(self):
- return SWFShapeRecord.TYPE_UNKNOWN
- def __str__(self):
- return " [SWFShapeRecord]"
- class SWFShapeRecordStraightEdge(SWFShapeRecord):
- def __init__(self, data, num_bits=0, level=1):
- self.num_bits = num_bits
- super(SWFShapeRecordStraightEdge, self).__init__(data, level)
- def parse(self, data, level=1):
- self.general_line_flag = (data.readUB(1) == 1)
- self.vert_line_flag = False if self.general_line_flag else (data.readUB(1) == 1)
- self.deltaX = data.readSB(self.num_bits) \
- if self.general_line_flag or not self.vert_line_flag \
- else 0.0
- self.deltaY = data.readSB(self.num_bits) \
- if self.general_line_flag or self.vert_line_flag \
- else 0.0
- @property
- def type(self):
- return SWFShapeRecord.TYPE_STRAIGHTEDGE
- def __str__(self):
- s = " [SWFShapeRecordStraightEdge]"
- if self.general_line_flag:
- s += " General: %d %d" % (self.deltaX, self.deltaY)
- else:
- if self.vert_line_flag:
- s += " Vertical: %d" % self.deltaY
- else:
- s += " Horizontal: %d" % self.deltaX
- return s
- class SWFShapeRecordCurvedEdge(SWFShapeRecord):
- def __init__(self, data, num_bits=0, level=1):
- self.num_bits = num_bits
- super(SWFShapeRecordCurvedEdge, self).__init__(data, level)
- def parse(self, data, level=1):
- self.control_deltaX = data.readSB(self.num_bits)
- self.control_deltaY = data.readSB(self.num_bits)
- self.anchor_deltaX = data.readSB(self.num_bits)
- self.anchor_deltaY = data.readSB(self.num_bits)
- @property
- def type(self):
- return SWFShapeRecord.TYPE_CURVEDEDGE
- def __str__(self):
- return " [SWFShapeRecordCurvedEdge]" + \
- " ControlDelta: %d, %d" % (self.control_deltaX, self.control_deltaY) + \
- " AnchorDelta: %d, %d" % (self.anchor_deltaX, self.anchor_deltaY)
- class SWFShapeRecordStyleChange(SWFShapeRecord):
- def __init__(self, data, states=0, fill_bits=0, line_bits=0, level=1):
- self.fill_styles = []
- self.line_styles = []
- self.state_new_styles = ((states & 0x10) != 0)
- self.state_line_style = ((states & 0x08) != 0)
- self.state_fill_style1 = ((states & 0x4) != 0)
- self.state_fill_style0 = ((states & 0x2) != 0)
- self.state_moveto = ((states & 0x1) != 0)
- self.num_fillbits = fill_bits
- self.num_linebits = line_bits
- self.move_deltaX = 0.0
- self.move_deltaY = 0.0
- self.fill_style0 = 0
- self.fill_style1 = 0
- self.line_style = 0
- super(SWFShapeRecordStyleChange, self).__init__(data, level)
- def parse(self, data, level=1):
- if self.state_moveto:
- movebits = data.readUB(5)
- self.move_deltaX = data.readSB(movebits)
- self.move_deltaY = data.readSB(movebits)
- self.fill_style0 = data.readUB(self.num_fillbits) if self.state_fill_style0 else 0
- self.fill_style1 = data.readUB(self.num_fillbits) if self.state_fill_style1 else 0
- self.line_style = data.readUB(self.num_linebits) if self.state_line_style else 0
- if self.state_new_styles:
- data.reset_bits_pending();
- num_fillstyles = self.readstyle_array_length(data, level)
- for i in range(0, num_fillstyles):
- self.fill_styles.append(data.readFILLSTYLE(level))
- num_linestyles = self.readstyle_array_length(data, level)
- for i in range(0, num_linestyles):
- if level <= 3:
- self.line_styles.append(data.readLINESTYLE(level))
- else:
- self.line_styles.append(data.readLINESTYLE2(level))
- self.num_fillbits = data.readUB(4)
- self.num_linebits = data.readUB(4)
- @property
- def type(self):
- return SWFShapeRecord.TYPE_STYLECHANGE
- def readstyle_array_length(self, data, level=1):
- length = data.readUI8()
- if level >= 2 and length == 0xff:
- length = data.readUI16()
- return length
- def __str__(self):
- return " [SWFShapeRecordStyleChange]" + \
- " moveTo: %d %d" % (self.move_deltaX, self.move_deltaY) + \
- " fs0: %d" % self.fill_style0 + \
- " fs1: %d" % self.fill_style1 + \
- " linestyle: %d" % self.line_style + \
- " flags: %d %d %d" % (self.state_fill_style0, self.state_fill_style1, self.state_line_style)
- class SWFShapeRecordEnd(SWFShapeRecord):
- def __init__(self):
- super(SWFShapeRecordEnd, self).__init__(None)
- def parse(self, data, level=1):
- pass
- @property
- def type(self):
- return SWFShapeRecord.TYPE_END
- def __str__(self):
- return " [SWFShapeRecordEnd]"
- class SWFMatrix(_dumb_repr):
- def __init__(self, data):
- self.scaleX = 1.0
- self.scaleY = 1.0
- self.rotateSkew0 = 0.0
- self.rotateSkew1 = 0.0
- self.translateX = 0.0
- self.translateY = 0.0
- if not data is None:
- self.parse(data)
- def parse(self, data):
- data.reset_bits_pending();
- self.scaleX = 1.0
- self.scaleY = 1.0
- if data.readUB(1) == 1:
- scaleBits = data.readUB(5)
- self.scaleX = data.readFB(scaleBits)
- self.scaleY = data.readFB(scaleBits)
- self.rotateSkew0 = 0.0
- self.rotateSkew1 = 0.0
- if data.readUB(1) == 1:
- rotateBits = data.readUB(5)
- self.rotateSkew0 = data.readFB(rotateBits)
- self.rotateSkew1 = data.readFB(rotateBits)
- translateBits = data.readUB(5)
- self.translateX = data.readSB(translateBits)
- self.translateY = data.readSB(translateBits)
- def to_array(self):
- return [
- self.scaleX, self.rotateSkew0,
- self.rotateSkew1, self.scaleY,
- self.translateX, self.translateY
- ]
- def __str__(self):
- def fmt(s):
- return "%0.2f" % s
- return "[%s]" % ",".join(map(fmt, self.to_array()))
- class SWFGradientRecord(_dumb_repr):
- def __init__(self, data=None, level=1):
- self._records = []
- if not data is None:
- self.parse(data, level)
- def parse(self, data, level=1):
- self.ratio = data.readUI8()
- self.color = data.readRGB() if level <= 2 else data.readRGBA()
- def __str__(self):
- return "[SWFGradientRecord] Color: %s, Ratio: %d" % (ColorUtils.to_rgb_string(self.color), self.ratio)
- class SWFGradient(_dumb_repr):
- def __init__(self, data=None, level=1):
- self._records = []
- self.focal_point = 0.0
- if not data is None:
- self.parse(data, level)
- @property
- def records(self):
- return self._records
- def parse(self, data, level=1):
- data.reset_bits_pending();
- self.spreadmethod = data.readUB(2)
- self.interpolation_mode = data.readUB(2)
- num_gradients = data.readUB(4)
- for i in range(0, num_gradients):
- self._records.append(data.readGRADIENTRECORD(level))
- def __str__(self):
- s = "[SWFGadient]"
- for record in self._records:
- s += "\n " + record.__str__()
- return s
- class SWFFocalGradient(SWFGradient):
- def __init__(self, data=None, level=1):
- super(SWFFocalGradient, self).__init__(data, level)
- def parse(self, data, level=1):
- super(SWFFocalGradient, self).parse(data, level)
- self.focal_point = data.readFIXED8()
- def __str__(self):
- return "[SWFFocalGradient] Color: %s, Ratio: %d, Focal: %0.2f" % \
- (ColorUtils.to_rgb_string(self.color), self.ratio, self.focal_point)
- class SWFFillStyle(_dumb_repr):
- def __init__(self, data=None, level=1):
- if not data is None:
- self.parse(data, level)
- COLOR = [0x0]
- GRADIENT = [0x10, 0x12, 0x13]
- BITMAP = [0x40, 0x41, 0x42, 0x43]
- def parse(self, data, level=1):
- self.type = data.readUI8()
- if self.type in SWFFillStyle.COLOR:
- self.rgb = data.readRGB() if level <= 2 else data.readRGBA()
- elif self.type in SWFFillStyle.GRADIENT:
- self.gradient_matrix = data.readMATRIX()
- self.gradient = data.readFOCALGRADIENT(level) if self.type == 0x13 else data.readGRADIENT(level)
- elif self.type in SWFFillStyle.BITMAP:
- self.bitmap_id = data.readUI16()
- self.bitmap_matrix = data.readMATRIX()
- else:
- raise Exception("Unknown fill style type: 0x%x" % self.type, level)
- def get_dependencies(self):
- return set([self.bitmap_id]) if self.type in SWFFillStyle.BITMAP else set()
- def __str__(self):
- s = "[SWFFillStyle] "
- if self.type in SWFFillStyle.COLOR:
- s += "Color: %s" % ColorUtils.to_rgb_string(self.rgb)
- elif self.type in SWFFillStyle.GRADIENT:
- s += "Gradient: %s" % self.gradient_matrix
- elif self.type in SWFFillStyle.BITMAP:
- s += "BitmapID: %d" % (self.bitmap_id)
- return s
- class SWFLineStyle(_dumb_repr):
- def __init__(self, data=None, level=1):
- # forward declarations for SWFLineStyle2
- self.start_caps_style = LineCapsStyle.ROUND
- self.end_caps_style = LineCapsStyle.ROUND
- self.joint_style = LineJointStyle.ROUND
- self.has_fill_flag = False
- self.no_hscale_flag = False
- self.no_vscale_flag = False
- self.pixelhinting_flag = False
- self.no_close = False
- self.miter_limit_factor = 3.0
- self.fill_type = None
- self.width = 1
- self.color = 0
- if not data is None:
- self.parse(data, level)
- def get_dependencies(self):
- return set()
- def parse(self, data, level=1):
- self.width = data.readUI16()
- self.color = data.readRGB() if level <= 2 else data.readRGBA()
- def __str__(self):
- s = "[SWFLineStyle] "
- s += "Color: %s, Width: %d" % (ColorUtils.to_rgb_string(self.color), self.width)
- return s
- class SWFLineStyle2(SWFLineStyle):
- def __init__(self, data=None, level=1):
- super(SWFLineStyle2, self).__init__(data, level)
- def parse(self, data, level=1):
- self.width = data.readUI16()
- self.start_caps_style = data.readUB(2)
- self.joint_style = data.readUB(2)
- self.has_fill_flag = (data.readUB(1) == 1)
- self.no_hscale_flag = (data.readUB(1) == 1)
- self.no_vscale_flag = (data.readUB(1) == 1)
- self.pixelhinting_flag = (data.readUB(1) == 1)
- data.readUB(5)
- self.no_close = (data.readUB(1) == 1)
- self.end_caps_style = data.readUB(2)
- if self.joint_style == LineJointStyle.MITER:
- self.miter_limit_factor = data.readFIXED8()
- if self.has_fill_flag:
- self.fill_type = data.readFILLSTYLE(level)
- else:
- self.color = data.readRGBA()
- def __str__(self):
- s = "[SWFLineStyle2] "
- s += "Width: %d, " % self.width
- s += "StartCapsStyle: %d, " % self.start_caps_style
- s += "JointStyle: %d, " % self.joint_style
- s += "HasFillFlag: %d, " % self.has_fill_flag
- s += "NoHscaleFlag: %d, " % self.no_hscale_flag
- s += "NoVscaleFlag: %d, " % self.no_vscale_flag
- s += "PixelhintingFlag: %d, " % self.pixelhinting_flag
- s += "NoClose: %d, " % self.no_close
- if self.joint_style:
- s += "MiterLimitFactor: %d" % self.miter_limit_factor
- if self.has_fill_flag:
- s += "FillType: %s, " % self.fill_type
- else:
- s += "Color: %s" % ColorUtils.to_rgb_string(self.color)
- return s
- class SWFMorphGradientRecord(_dumb_repr):
- def __init__(self, data):
- if not data is None:
- self.parse(data)
- def parse(self, data):
- self.startRatio = data.readUI8()
- self.startColor = data.readRGBA()
- self.endRatio = data.readUI8()
- self.endColor = data.readRGBA()
- class SWFMorphGradient(_dumb_repr):
- def __init__(self, data, level=1):
- self.records = []
- if not data is None:
- self.parse(data, level)
- def parse(self, data, level=1):
- self.records = []
- numGradients = data.readUI8()
- for i in range(0, numGradients):
- self.records.append(data.readMORPHGRADIENTRECORD())
- class SWFMorphFillStyle(_dumb_repr):
- def __init__(self, data, level=1):
- if not data is None:
- self.parse(data, level)
- def get_dependencies(self):
- return set([self.bitmapId]) if hasattr(self, 'bitmapId') else set()
- def parse(self, data, level=1):
- type = data.readUI8()
- if type == 0x0:
- self.startColor = data.readRGBA()
- self.endColor = data.readRGBA()
- elif type in [0x10, 0x12]:
- self.startGradientMatrix = data.readMATRIX()
- self.endGradientMatrix = data.readMATRIX()
- self.gradient = data.readMORPHGRADIENT(level)
- elif type in [0x40, 0x41, 0x42, 0x43]:
- self.bitmapId = data.readUI16()
- self.startBitmapMatrix = data.readMATRIX()
- self.endBitmapMatrix = data.readMATRIX()
- class SWFMorphLineStyle(_dumb_repr):
- def __init__(self, data, level=1):
- # Forward declaration of SWFMorphLineStyle2 properties
- self.startCapsStyle = LineCapsStyle.ROUND
- self.endCapsStyle = LineCapsStyle.ROUND
- self.jointStyle = LineJointStyle.ROUND
- self.hasFillFlag = False
- self.noHScaleFlag = False
- self.noVScaleFlag = False
- self.pixelHintingFlag = False
- self.noClose = False
- self.miterLimitFactor = 3
- self.fillType = None
- if not data is None:
- self.parse(data, level)
- def parse(self, data, level=1):
- self.startWidth = data.readUI16()
- self.endWidth = data.readUI16()
- self.startColor = data.readRGBA()
- self.endColor = data.readRGBA()
- class SWFMorphLineStyle2(SWFMorphLineStyle):
- def __init__(self, data, level=1):
- super(SWFMorphLineStyle2, self).__init__(data, level)
- def parse(self, data, level=1):
- self.startWidth = data.readUI16()
- self.endWidth = data.readUI16()
- self.startCapsStyle = data.readUB(2)
- self.jointStyle = data.readUB(2)
- self.hasFillFlag = (data.readUB(1) == 1)
- self.noHScaleFlag = (data.readUB(1) == 1)
- self.noVScaleFlag = (data.readUB(1) == 1)
- self.pixelHintingFlag = (data.readUB(1) == 1)
- reserved = data.readUB(5);
- self.noClose = (data.readUB(1) == 1)
- self.endCapsStyle = data.readUB(2)
- if self.jointStyle == LineJointStyle.MITER:
- self.miterLimitFactor = data.readFIXED8()
- if self.hasFillFlag:
- self.fillType = data.readMORPHFILLSTYLE(level)
- else:
- self.startColor = data.readRGBA()
- self.endColor = data.readRGBA()
- class SWFRecordHeader(_dumb_repr):
- def __init__(self, type, content_length, header_length):
- self.type = type
- self.content_length = content_length
- self.header_length = header_length
- @property
- def tag_length(self):
- return self.header_length + self.content_length
- class SWFRectangle(_dumb_repr):
- def __init__(self):
- self.xmin = self.xmax = self.ymin = self.ymax = 0
- def parse(self, s):
- s.reset_bits_pending()
- bits = s.readUB(5)
- self.xmin = s.readSB(bits)
- self.xmax = s.readSB(bits)
- self.ymin = s.readSB(bits)
- self.ymax = s.readSB(bits)
- @property
- def dimensions(self):
- """
- Returns dimensions as (x, y) tuple.
- """
- return (self.xmax - self.xmin, self.ymax - self.ymin)
- def __str__(self):
- return "[xmin: %d xmax: %d ymin: %d ymax: %d]" % (self.xmin/20, self.xmax/20, self.ymin/20, self.ymax/20)
- class SWFColorTransform(_dumb_repr):
- def __init__(self, data=None):
- if not data is None:
- self.parse(data)
- def parse(self, data):
- data.reset_bits_pending()
- self.hasAddTerms = (data.readUB(1) == 1)
- self.hasMultTerms = (data.readUB(1) == 1)
- bits = data.readUB(4)
- self.rMult = 1
- self.gMult = 1
- self.bMult = 1
- if self.hasMultTerms:
- self.rMult = data.readSB(bits)
- self.gMult = data.readSB(bits)
- self.bMult = data.readSB(bits)
- self.rAdd = 0
- self.gAdd = 0
- self.bAdd = 0
- if self.hasAddTerms:
- self.rAdd = data.readSB(bits)
- self.gAdd = data.readSB(bits)
- self.bAdd = data.readSB(bits)
- @property
- def matrix(self):
- return [
- self.rMult / 256.0, 0.0, 0.0, 0.0, self.rAdd / 256.0,
- 0.0, self.gMult / 256.0, 0.0, 0.0, self.gAdd / 256.0,
- 0.0, 0.0, self.bMult / 256.0, 0.0, self.bAdd / 256.0,
- 0.0, 0.0, 0.0, 1.0, 1.0
- ]
- def __str__(self):
- return "[%d %d %d %d %d %d]" % \
- (self.rMult, self.gMult, self.bMult, self.rAdd, self.gAdd, self.bAdd)
- class SWFColorTransformWithAlpha(SWFColorTransform):
- def __init__(self, data=None):
- super(SWFColorTransformWithAlpha, self).__init__(data)
- def parse(self, data):
- data.reset_bits_pending()
- self.hasAddTerms = (data.readUB(1) == 1)
- self.hasMultTerms = (data.readUB(1) == 1)
- bits = data.readUB(4)
- self.rMult = 1
- self.gMult = 1
- self.bMult = 1
- self.aMult = 1
- if self.hasMultTerms:
- self.rMult = data.readSB(bits)
- self.gMult = data.readSB(bits)
- self.bMult = data.readSB(bits)
- self.aMult = data.readSB(bits)
- self.rAdd = 0
- self.gAdd = 0
- self.bAdd = 0
- self.aAdd = 0
- if self.hasAddTerms:
- self.rAdd = data.readSB(bits)
- self.gAdd = data.readSB(bits)
- self.bAdd = data.readSB(bits)
- self.aAdd = data.readSB(bits)
- @property
- def matrix(self):
- '''
- Gets the matrix as a 20 item list
- '''
- return [
- self.rMult / 256.0, 0.0, 0.0, 0.0, self.rAdd / 256.0,
- 0.0, self.gMult / 256.0, 0.0, 0.0, self.gAdd / 256.0,
- 0.0, 0.0, self.bMult / 256.0, 0.0, self.bAdd / 256.0,
- 0.0, 0.0, 0.0, self.aMult / 256.0, self.aAdd / 256.0
- ]
- def __str__(self):
- return "[%d %d %d %d %d %d %d %d]" % \
- (self.rMult, self.gMult, self.bMult, self.aMult, self.rAdd, self.gAdd, self.bAdd, self.aAdd)
- class SWFFrameLabel(_dumb_repr):
- def __init__(self, frameNumber, name):
- self.frameNumber = frameNumber
- self.name = name
- def __str__(self):
- return "Frame: %d, Name: %s" % (self.frameNumber, self.name)
- class SWFScene(_dumb_repr):
- def __init__(self, offset, name):
- self.offset = offset
- self.name = name
- def __str__(self):
- return "Scene: %d, Name: '%s'" % (self.offset, self.name)
- class SWFSymbol(_dumb_repr):
- def __init__(self, data=None):
- if not data is None:
- self.parse(data)
- def parse(self, data):
- self.tagId = data.readUI16()
- self.name = data.readString()
- def __str__(self):
- return "ID %d, Name: %s" % (self.tagId, self.name)
- class SWFGlyphEntry(_dumb_repr):
- def __init__(self, data=None, glyphBits=0, advanceBits=0):
- if not data is None:
- self.parse(data, glyphBits, advanceBits)
- def parse(self, data, glyphBits, advanceBits):
- # GLYPHENTRYs are not byte aligned
- self.index = data.readUB(glyphBits)
- self.advance = data.readSB(advanceBits)
- def __str__(self):
- return "Index: %d, Advance: %d" % (self.index, self.advance)
- class SWFKerningRecord(_dumb_repr):
- def __init__(self, data=None, wideCodes=False):
- if not data is None:
- self.parse(data, wideCodes)
- def parse(self, data, wideCodes):
- self.code1 = data.readUI16() if wideCodes else data.readUI8()
- self.code2 = data.readUI16() if wideCodes else data.readUI8()
- self.adjustment = data.readSI16()
- def __str__(self):
- return "Code1: %d, Code2: %d, Adjustment: %d" % (self.code1, self.code2, self.adjustment)
- class SWFTextRecord(_dumb_repr):
- def __init__(self, data=None, glyphBits=0, advanceBits=0, previousRecord=None, level=1):
- self.hasFont = False
- self.hasColor = False
- self.hasYOffset = False
- self.hasXOffset = False
- self.fontId = -1
- self.textColor = 0
- self.xOffset = 0
- self.yOffset = 0
- self.textHeight = 12
- self.glyphEntries = []
- if not data is None:
- self.parse(data, glyphBits, advanceBits, previousRecord, level)
- def get_dependencies(self):
- return set([self.fontId]) if self.hasFont else set()
- def parse(self, data, glyphBits, advanceBits, previousRecord=None, level=1):
- self.glyphEntries = []
- styles = data.readUI8()
- self.type = styles >> 7
- self.hasFont = ((styles & 0x08) != 0)
- self.hasColor = ((styles & 0x04) != 0)
- self.hasYOffset = ((styles & 0x02) != 0)
- self.hasXOffset = ((styles & 0x01) != 0)
- if self.hasFont:
- self.fontId = data.readUI16()
- elif not previousRecord is None:
- self.fontId = previousRecord.fontId
- if self.hasColor:
- self.textColor = data.readRGB() if level < 2 else data.readRGBA()
- elif not previousRecord is None:
- self.textColor = previousRecord.textColor
- if self.hasXOffset:
- self.xOffset = data.readSI16();
- elif not previousRecord is None:
- self.xOffset = previousRecord.xOffset
- if self.hasYOffset:
- self.yOffset = data.readSI16();
- elif not previousRecord is None:
- self.yOffset = previousRecord.yOffset
- if self.hasFont:
- self.textHeight = data.readUI16()
- elif not previousRecord is None:
- self.textHeight = previousRecord.textHeight
- glyphCount = data.readUI8()
- for i in range(0, glyphCount):
- self.glyphEntries.append(data.readGLYPHENTRY(glyphBits, advanceBits))
- def __str__(self):
- return "[SWFTextRecord]"
- class SWFClipActions(_dumb_repr):
- def __init__(self, data=None, version=0):
- self.eventFlags = None
- self.records = []
- if not data is None:
- self.parse(data, version)
- def parse(self, data, version):
- data.readUI16() # reserved, always 0
- self.eventFlags = data.readCLIPEVENTFLAGS(version)
- self.records = []
- record = data.readCLIPACTIONRECORD(version)
- while not record is None:
- self.records.append(record)
- record = data.readCLIPACTIONRECORD(version)
- def __str__(self):
- return "[SWFClipActions]"
- class SWFClipActionRecord(_dumb_repr):
- def __init__(self, data=None, version=0):
- self.eventFlags = None
- self.keyCode = 0
- self.actions = []
- if not data is None:
- self.parse(data, version)
- def parse(self, data, version):
- self.actions = []
- self.eventFlags = data.readCLIPEVENTFLAGS(version)
- data.readUI32() # actionRecordSize, not needed here
- if self.eventFlags.keyPressEvent:
- self.keyCode = data.readUI8()
- action = data.readACTIONRECORD()
- while not action is None:
- self.actions.append(action)
- action = data.readACTIONRECORD()
- def __str__(self):
- return "[SWFClipActionRecord]"
- class SWFClipEventFlags(_dumb_repr):
- keyUpEvent = False
- keyDownEvent = False
- mouseUpEvent = False
- mouseDownEvent = False
- mouseMoveEvent = False
- unloadEvent = False
- enterFrameEvent = False
- loadEvent = False
- dragOverEvent = False # SWF6
- rollOutEvent = False # SWF6
- rollOverEvent = False # SWF6
- releaseOutsideEvent = False # SWF6
- releaseEvent = False # SWF6
- pressEvent = False # SWF6
- initializeEvent = False # SWF6
- dataEvent = False
- constructEvent = False # SWF7
- keyPressEvent = False # SWF6
- dragOutEvent = False # SWF6
- def __init__(self, data=None, version=0):
- if not data is None:
- self.parse(data, version)
- def parse(self, data, version):
- flags1 = data.readUI8();
- self.keyUpEvent = ((flags1 & 0x80) != 0)
- self.keyDownEvent = ((flags1 & 0x40) != 0)
- self.mouseUpEvent = ((flags1 & 0x20) != 0)
- self.mouseDownEvent = ((flags1 & 0x10) != 0)
- self.mouseMoveEvent = ((flags1 & 0x08) != 0)
- self.unloadEvent = ((flags1 & 0x04) != 0)
- self.enterFrameEvent = ((flags1 & 0x02) != 0)
- self.loadEvent = ((flags1 & 0x01) != 0)
- flags2 = data.readUI8()
- self.dragOverEvent = ((flags2 & 0x80) != 0)
- self.rollOutEvent = ((flags2 & 0x40) != 0)
- self.rollOverEvent = ((flags2 & 0x20) != 0)
- self.releaseOutsideEvent = ((flags2 & 0x10) != 0)
- self.releaseEvent = ((flags2 & 0x08) != 0)
- self.pressEvent = ((flags2 & 0x04) != 0)
- self.initializeEvent = ((flags2 & 0x02) != 0)
- self.dataEvent = ((flags2 & 0x01) != 0)
- if version >= 6:
- flags3 = data.readUI8()
- self.constructEvent = ((flags3 & 0x04) != 0)
- self.keyPressEvent = ((flags3 & 0x02) != 0)
- self.dragOutEvent = ((flags3 & 0x01) != 0)
- data.readUI8() # reserved, always 0
- def __str__(self):
- return "[SWFClipEventFlags]"
- class SWFZoneData(_dumb_repr):
- def __init__(self, data=None):
- if not data is None:
- self.parse(data)
- def parse(self, data):
- self.alignmentCoordinate = data.readFLOAT16()
- self.zoneRange = data.readFLOAT16()
- def __str__(self):
- return "[SWFZoneData]"
- class SWFZoneRecord(_dumb_repr):
- def __init__(self, data=None):
- if not data is None:
- self.parse(data)
- def parse(self, data):
- self.zoneData = []
- numZoneData = data.readUI8()
- for i in range(0, numZoneData):
- self.zoneData.append(data.readZONEDATA())
- mask = data.readUI8()
- self.maskX = ((mask & 0x01) != 0)
- self.maskY = ((mask & 0x02) != 0)
- def __str__(self):
- return "[SWFZoneRecord]"
- class SWFSoundInfo(_dumb_repr):
- def __init__(self, data=None):
- if not data is None:
- self.parse(data)
- def parse(self, data):
- reserved = data.readUB(2)
- assert reserved == 0
- self.syncStop = data.readUB(1) == 1
- self.syncNoMultiple = data.readUB(1) == 1
- self.hasEnvelope = data.readUB(1) == 1
- self.hasLoops = data.readUB(1) == 1
- self.hasOutPoint = data.readUB(1) == 1
- self.hasInPoint = data.readUB(1) == 1
- self.inPoint = data.readUI32() if self.hasInPoint else None
- self.outPoint = data.readUI32() if self.hasOutPoint else None
- self.loopCount = data.readUI16() if self.hasLoops else None
- self.envPointCount = data.readUI8() if self.hasEnvelope else None
- self.envelopePoints = [data.readSOUNDENVELOPE() for x in xrange(self.envPointCount)] if self.hasEnvelope else None
- def __str__(self):
- return "[SWFSoundInfo]"
- class SWFSoundEnvelope(_dumb_repr):
- def __init__(self, data=None):
- if not data is None:
- self.parse(data)
- def parse(self, data):
- self.position = data.readUI32()
- self.leftLevel = data.readUI16()
- self.rightLevel = data.readUI16()
- def __str__(self):
- return "[SWFSoundEnvelope]"
- class SWFButtonRecord(_dumb_repr):
- def __init__(self, version, data=None):
- # version is 1 for DefineButton, 2 for DefineButton2, etc
- if not data is None:
- self.parse(data, version)
- def get_dependencies(self):
- return set([self.characterId]) if self.valid else set()
- def parse(self, data, version):
- reserved0 = data.readUB(2)
- self.hasBlendMode = data.readUB(1) == 1
- self.hasFilterList = data.readUB(1) == 1
- self.stateHitTest = data.readUB(1) == 1
- self.stateDown = data.readUB(1) == 1
- self.stateOver = data.readUB(1) == 1
- self.stateUp = data.readUB(1) == 1
- self.valid = reserved0 or self.hasBlendMode or \
- self.hasFilterList or self.stateHitTest or \
- self.stateDown or self.stateOver or self.stateUp
- if not self.valid:
- return
- self.characterId = data.readUI16()
- self.placeDepth = data.readUI16()
- self.placeMatrix = data.readMATRIX()
- if version == 2:
- self.colorTransform = data.readCXFORMWITHALPHA()
- self.filterList = data.readFILTERLIST() if self.hasFilterList else None
- self.blendMode = data.readUI8() if self.hasBlendMode else 0
- def __str__(self):
- return "[SWFButtonRecord]"
- def __repr__(self):
- return "[SWFButtonRecord %r]" % self.__dict__
- class SWFButtonCondAction(_dumb_repr):
- def __init__(self, data=None):
- if not data is None:
- self.parse(data)
- def parse(self, data):
- self.idleToOverDown = data.readUB(1) == 1
- self.outDownToIdle = data.readUB(1) == 1
- self.outDownToOverDown = data.readUB(1) == 1
- self.overDownToOutDown = data.readUB(1) == 1
- self.overDownToOverUp = data.readUB(1) == 1
- self.overUpToOverDown = data.readUB(1) == 1
- self.overUpToIdle = data.readUB(1) == 1
- self.idleToOverUp = data.readUB(1) == 1
- self.keyPress = data.readUB(7)
- self.overDownToIdle = data.readUB(1) == 1
- self.actions = data.readACTIONRECORDs()
- def __str__(self):
- return "[SWFButtonCondAction]"
- class SWFExport(_dumb_repr):
- def __init__(self, data=None):
- if not data is None:
- self.parse(data)
- def get_dependencies(self):
- return set([self.characterId])
- def parse(self, data):
- self.characterId = data.readUI16()
- self.characterName = data.readString()
- def __str__(self):
- return "[SWFExport %d as %r]" % (self.characterId, self.characterName)
|