Using FLASM or SWFMILL to assemble/disassemble for swf files. Other options? - actionscript-3

We have a relatively simple SWF created by a 3rd-person that basically moves around some text. I need to be able to modify that text daily, but I don't have Flash and I don't know how to use Flash. So opening and modifying it in Flash is not an option. External files are not an option either.
I tried using FLASM and SWFMILL to disassemble the SWF, but the result doesn't display the actual text.
With FLASM I used flasm -d main_ver3.swf > main_ver3.flm. This was the result: https://dl.dropboxusercontent.com/u/10067449/Flash/main_ver3.flm
With swfmill I used swfmill swf2xml main_ver3.swf main_ver3.xml. This was the result: https://dl.dropboxusercontent.com/u/10067449/Flash/main_ver3.xml
In neither of them I see some of the text that was added to the Flash, for example, "Blackberry Curve", "Apple iphone", "Nokia Lumia".
What could the problem be? The text was created using Flash's Text tool.
Thanks.

Yes, unfortunately it's not going to be as easy as replacing a text string. SWF is a complex format with a lot of possibilities. In your case the font is embedded as a set of glyphs, and the glyphs (letters) are referenced in the text objects.
The comic sans font is defined under this tag:
<DefineFont3 objectID="15" isShiftJIS="0" isUnicode="0" isANSII="0" wideGlyphOffsets="0" italic="0" bold="0" language="1" name="Comic Sans MS">
This tag has a bunch of glyphs defined in it, and you'll notice the 10th glyph (index of 9 if you start counting from 0) has a map="65" value:
<Glyph map="65">
<GlyphShape>
<edges>
<ShapeSetup x="12500" y="300" fillStyle0="1"/>
<CurveTo x1="-920" y1="0" x2="-680" y2="-2360"/>
<CurveTo x1="-260" y1="-900" x2="-390" y2="-2250"/>
...
Decimal "65" is a capital A in ASCII. So the above draw calls are drawing a capital A. Later the Text record that starts with a glyph 9 (ascii 65, capital A) and spells out 'Apple iPhone' is (I've added the letters):
<DefineText objectID="22">
<bounds>
<Rectangle left="26" right="2560" top="81" bottom="574"/>
</bounds>
<transform>
<Transform transX="0" transY="0"/>
</transform>
<records>
<TextRecord>
<records>
<TextRecord6 isSetup="1" objectID="15" y="440" fontHeight="400">
<color>
<Color red="255" green="255" blue="255"/>
</color>
</TextRecord6>
<TextRecord6 isSetup="0">
<glyphs>
<TextEntry glyph="9" advance="293"/> # 9 = A
<TextEntry glyph="25" advance="214"/> # 25 = p
<TextEntry glyph="25" advance="214"/> # 25 = p
<TextEntry glyph="21" advance="110"/> # 21 = l
<TextEntry glyph="17" advance="219"/> # 17 = e
<TextEntry glyph="0" advance="120"/> # 0 = space
<TextEntry glyph="19" advance="112"/> # 19 = i
<TextEntry glyph="25" advance="214"/> # 25 = P
<TextEntry glyph="18" advance="231"/> # 18 = h
<TextEntry glyph="24" advance="210"/> # 24 = o
<TextEntry glyph="23" advance="209"/> # 23 = n
<TextEntry glyph="17" advance="219"/> # 17 = e
</glyphs>
</TextRecord6>
<TextRecord6 isSetup="0">
<glyphs/>
</TextRecord6>
</records>
</TextRecord>
</records>
</DefineText>
I'm not sure what the advance="###" is, but I'm guessing it's defining letter spacing. The l, i and space are only about 100 units wide, while the other letters are about 200 units.
Also, SWFs are compact, so it's not guaranteed that you have every glyph necessary to replace the text at will - it might only have the glyphs needed to render the text already in the SWF.
So in short, it is possible to modify the SWF with these tools, but it'd be a bit of digging and effort for you to change this text.
Also note that you could build a SWF that decompiled with a simple replaceable textfield if the designer was careful. It would need to pick up the text for the textfield from an Array defined in AS3 code (aka actions).

Related

How can I set the numbering of the x-axis of an Octave plot to engineering notation?

I made a very simple Octave script
a = [10e6, 11e6, 12e6];
b = [10, 11, 12];
plot(a, b, 'rd-')
which outputs the following graph.
Graph
Is it possible to set the numbering on the x-axis to engineering notation, rather than scientific, and have it display "10.5e+6, 11e+6, 11.5e+6" instead of "1.05e+7, 1.1e+7, 1.15+e7"?
While octave provides a 'short eng' formatting option, which does what you're asking for in terms of printing to the terminal, it does not appear to provide this functionality in plots or when formatting strings via sprintf.
Therefore you'll have to find a way to do this by yourself, with some creative string processing of the initial xticks, and substituting the plot's ticklabels accordingly. Thankfully it's not that hard :)
Using your example:
a = [10e6, 11e6, 12e6];
b = [10, 11, 12];
plot(a, b, 'rd-')
format short eng % display stdout in engineering format
TickLabels = disp( xticks ) % collect string as it would be displayed on the stdout
TickLabels = strsplit( TickLabels ) % tokenize at spaces
TickLabels = TickLabels( 2 : end - 1 ) % discard start and end empty tokens
TickLabels = regexprep( TickLabels, '\.0+e', 'e' ) % remove purely zero decimals using a regular expression
TickLabels = regexprep( TickLabels, '(\.[1-9]*)0+e', '$1e' ) % remove non-significant zeros in non-zero decimals using a regular expression
xticklabels( TickLabels ) % set the new ticklabels to the plot
format % reset short eng format back to default, if necessary

pie chart from csv file in LaTeX and pgf-pie

I am trying to draw a pie chart from a csv file using pgf-pie. And it must be pdf-pie, because datapie does not work for me under Debian 11. It did work under Debian 10. So I'm trying pgf-pie and I'm not interested in other solutions with other packages.
\documentclass{article}
\usepackage{csvsimple}
\usepackage{pgf-pie}
\begin{document}
\begin{filecontents*}{fruit.csv}
Name,Quantity
"Apples",30
"Pears",25
"Lemons,Limes",40.5
"Peaches",34.5
"Cherries",20
\end{filecontents*}
\csvreader[]{fruit.csv}{Name = \Name, Quantity = \Quantity}{\Quantity/\Name,}
\begin{tikzpicture}
\pie[polar, explode=0.1]{
\csvreader[]{fruit.csv}{Name = \Name, Quantity = \Quantity}{\Quantity/\Name,}
}
\end{tikzpicture}
\end{document}
The first \csvreader prints
30/”Apples”,25/”Pears”,34.5/”Peaches”,20/”Cherries”,
But that is wrong, because it doesn't print 40.5/"Lemons,Limes".
And the second \csvreader hangs pdflatex for ever with this error message:
! Use of \csv#reader doesn't match its definition.
\#ifnextchar ...eserved#d =#1\def \reserved#a {#2}
\def \reserved#b {#3}\futu...
l.2091 }
Why does this not work?
For the first part the problem is that , is normally used as a separation character in the csv file, so you need to protect it inside a group:
\documentclass{article}
\usepackage{csvsimple}
\usepackage{pgf-pie}
\begin{filecontents*}[overwrite]{fruit.csv}
Name,Quantity
"Apples",30
"Pears",25
"Lemons{,}Limes",40.5
"Peaches",34.5
"Cherries",20
\end{filecontents*}
\begin{document}
\csvreader[]{fruit.csv}{Name = \Name, Quantity = \Quantity}{\Quantity/\Name,}
\end{document}
or you could use another separator to avoid the conflict:
\documentclass{article}
\usepackage{csvsimple}
\usepackage{pgf-pie}
\begin{filecontents*}[overwrite]{fruit.csv}
Name;Quantity
"Apples";30
"Pears";25
"Lemons,Limes";40.5
"Peaches";34.5
"Cherries";20
\end{filecontents*}
\begin{document}
\csvreader[separator=semicolon]{fruit.csv}{Name = \Name, Quantity = \Quantity}{\Quantity/\Name,}
\end{document}
And for the pie chart problem, you don't actually need the pgf-pie package. Instead you could use the example from the csvsimple documentation:
\documentclass{article}
\usepackage{csvsimple}
\usepackage{pgf-pie}
\begin{filecontents*}[overwrite]{fruit.csv}
Name,Quantity
"Apples",30
"Pears",25
"Lemons{,}Limes",40.5
"Peaches",34.5
"Cherries",20
\end{filecontents*}
\begin{document}
% From the csvsimple doc:
% This example needs the packages tikz, xcolor, calc
\definecolorseries{myseries}{rgb}{step}[rgb]{.95,.85,.55}{.17,.47,.37}
\resetcolorseries{myseries}%
% a pie slice
\newcommand{\slice}[4]{
\pgfmathsetmacro{\midangle}{0.5*#1+0.5*#2}
\begin{scope}
\clip (0,0) -- (#1:1) arc (#1:#2:1) -- cycle;
\colorlet{SliceColor}{myseries!!+}%
\fill[inner color=SliceColor!30,outer color=SliceColor!60] (0,0) circle (1cm);
\end{scope}
\draw[thick] (0,0) -- (#1:1) arc (#1:#2:1) -- cycle;
\node[label=\midangle:#4] at (\midangle:1) {};
\pgfmathsetmacro{\temp}{min((#2-#1-10)/110*(-0.3),0)}
\pgfmathsetmacro{\innerpos}{max(\temp,-0.5) + 0.8}
\node at (\midangle:\innerpos) {#3};
}
% sum of amounts
\csvreader[before reading=\def\mysum{0}]{fruit.csv}{Quantity=\Quantity}{%
\pgfmathsetmacro{\mysum}{\mysum+\Quantity}%
}
% drawing of the pie chart
\begin{tikzpicture}[scale=3]%
\def\mya{0}\def\myb{0}
\csvreader[head to column names]{fruit.csv}{}{%
\let\mya\myb
\pgfmathsetmacro{\myb}{\myb+\Quantity}
\slice{\mya/\mysum*360}{\myb/\mysum*360}{\Quantity}{\Name}
}
\end{tikzpicture}%
\end{document}

Octave buffering console output

I'm new to Octave.
I'm working with a huge matrix with thousands of rows and just 2 columns.
When I print it the terminal seems to be cutting part of it, but I want the whole thing to be shown.
Any way to do that or maybe to redirect the output in a file or something?
I had the same in problem in Eclipse but it was much easier to solve the same issue back then.
to redirect a Matrix to a file use save
A=rand(5,5)
A =
0.552789 0.570720 0.896715 0.982821 0.622758
0.704791 0.514302 0.380680 0.344768 0.459588
0.230478 0.744468 0.668264 0.659316 0.414710
0.819015 0.572315 0.404128 0.074092 0.813156
0.099461 0.031186 0.499781 0.758091 0.243281
save("-ascii","file-ascii.txt","A")
save("file-text.txt","A")
pure text
$ cat file-ascii.txt
5.52789005e-01 5.70719716e-01 8.96714571e-01 9.82821412e-01 6.22757836e-01
7.04791031e-01 5.14301972e-01 3.80679512e-01 3.44768074e-01 4.59587827e-01
2.30478499e-01 7.44467506e-01 6.68264066e-01 6.59315817e-01 4.14709954e-01
8.19014881e-01 5.72314594e-01 4.04128230e-01 7.40916214e-02 8.13155903e-01
9.94607828e-02 3.11857103e-02 4.99780576e-01 7.58091470e-01 2.43280663e-01
octave default style
$ cat file-text.txt
# Created by Octave 5.2.0, Wed May 27 21:43:22 2020 CEST <Marco#LAPTOP-82F08ILC>
# name: A
# type: matrix
# rows: 5
# columns: 5
0.55278900467056769 0.57071971558810353 0.89671457115004172 0.98282141203898321 0.622757835845834
0.70479103140202992 0.51430197227101204 0.3806795123567624 0.34476807355856237 0.45958782700965189
0.2304784985452572 0.74446750644064241 0.66826406647042169 0.65931581744685042 0.41470995365627888
0.81901488130574696 0.57231459443213173 0.40412823039438278 0.074091621362711677 0.81315590327055964
0.099460782832668723 0.031185710267227097 0.49978057628118927 0.75809147040922908 0.24328066285306477

How to automatically crop an .OBJ 3D model to a bounding box?

In the now obsoleted Autodesk ReCap API it was possible to specify a "bounding box" around the scene to be generated from images.
In the resulting models, any vertices outside the bounding box were discarded, and any volumes that extended beyond the bounding box were truncated to have faces at the box boundaries.
I am now using Autodesk's Forge Reality Capture API which replaced ReCap. Apparently, This new API does not allow the user to specify a bounding box.
So I am now searching for a program that takes an .OBJ file and a specified bounding box as input, and outputs a file of just the vertices and faces within this bounding box.
Given that there is no way to specify the bounding box in Reality Capture API, I created this python program. It is crude, in that it only discards faces that have vertices that are outside the bounding box. And it actually does discards nondestructively, only by commenting them out in the output OBJ file. This allows you to uncomment them and then use a different bounding box.
This may not be what you need if you truly want to remove all relevant v, vn, vt, vp and f lines that are outside the bounding box, because the OBJ file size remains mostly unchanged. But for my particular needs, keeping all the records and just using comments was preferable.
# obj3Dcrop.py
# (c) Scott L. McGregor, Dec 2019
# License: free for all non commercial uses. Contact author for any other uses.
# Changes and Enhancements must be shared with author, and be subject to same use terms
# TL;DR: This program uses a bounding box, and "crops" faces and vertices from a
# Wavefront .OBJ format file, created by Autodesk Forge Reality Capture API
# if one of the vertices in a face is not within the bounds of the box.
#
# METHOD
# 1) All lines other than "v" vertex definitions and "f" faces definitions
# are copied UNCHANGED from the input .OBJ file to an output .OBJ file.
# 2) All "v" vertex definition lines have their (x, y, z) positions tested to see if:
# minX < x < maxX and minY < y < maxY and minZ < z < maxZ ?
# If TRUE, we want to keep this vertex in the new OBJ, so we
# store its IMPLICIT ORDINAL position in the file in a dictionary called v_keepers.
# If FALSE, we will use its absence from the v_keepers file as a way to identify
# faces that contain it and drop them. All "v" lines are also copied unchanged to the
# output file.
# 3) All "f" lines (face definitions) are inspected to verify that all 3 vertices in the face
# are in the v_keepers list. If they are, the f line is output unchanged.
# 4) Any "f" line that refers to a vertex that was cropped, is prefixed by "# CROPPED: "
# in the output file. Lines beginning # are treated as comments, and ignored in future
# processing.
# KNOWN LIMITATIONS: This program generates models in which the outside of bound faces
# have been removed. The vertices that were found outside the bounding box, are still in the
# OBJ file, but they are now disconnected and therefore ignored in later processing.
# The "f" lines for faces with vertices outside the bounding box are also still in the
# output file, but now commented out, so they don't process. Because this is non-destructive.
# we can easily change our bounding box later, uncomment cropped lines and reprocess.
#
# This might be an incomplete solution for some potential users. For such users
# a more complete program would delete unneeded v, vn, vt and vp lines when the v vertex
# that they refer to is dropped. But note that this requires renumbering all references to these
# vertice definitions in the "f" face definition lines. Such a more complete solution would also
# DISCARD all 'f' lines with any vertices that are out of bounds, instead of making them copies.
# Such a rewritten .OBJ file would be var more compact, but changing the bounding box would require
# saving the pre-cropped original.
# QUIRK: The OBJ file format defines v, vn, vt, vp and f elements by their
# IMPLICIT ordinal occurrence in the file, with each element type maintaining
# its OWN separate sequence. It then references those definitions EXPLICITLY in
# f face definitions. So deleting (or commenting out) element references requires
# appropriate rewriting of all the"f"" lines tracking all the new implicit positions.
# Such rewriting is not particularly hard to do, but it is one more place to make
# a mistake, and could make the algorithm more complicated to understand.
# This program doesn't bother, because all further processing of the output
# OBJ file ignores unreferenced v, vn, vt and vp elements.
#
# Saving all lines rather than deleting them to save space is a tradeoff involving considerations of
# Undo capability, compute cycles, compute space (unreferenced lines) and maintenance complexity choice.
# It is left to the motivated programmer to add this complexity if needed.
import sys
#bounding_box = sys.argv[1] # should be in the only string passsed (maxX, maxY, maxZ, minX, minY, minZ)
bounding_box = [10, 10, 10, -10, -10, 1]
maxX = bounding_box[0]
maxY = bounding_box[1]
maxZ = bounding_box[2]
minX = bounding_box[3]
minY = bounding_box[4]
minZ = bounding_box[5]
v_keepers = dict() # keeps track of which vertices are within the bounding box
kept_vertices = 0
discarded_vertices = 0
kept_faces = 0
discarded_faces = 0
discarded_lines = 0
kept_lines = 0
obj_file = open('sample.obj','r')
new_obj_file = open('cropped.obj','w')
# the number of the next "v" vertex lines to process.
original_v_number = 1 # the number of the next "v" vertex lines to process.
new_v_number = 1 # the new ordinal position of this vertex if out of bounds vertices were discarded.
for line in obj_file:
line_elements = line.split()
# Python doesn't have a SWITCH statement, but we only have three cases, so we'll just use cascading if stmts
if line_elements[0] != "f": # if it isn't an "f" type line (face definition)
if line_elements[0] != "v": # and it isn't an "v" type line either (vertex definition)
# ************************ PROCESS ALL NON V AND NON F LINE TYPES ******************
# then we just copy it unchanged from the input OBJ to the output OBJ
new_obj_file.write(line)
kept_lines = kept_lines + 1
else: # then line_elements[0] == "v":
# ************************ PROCESS VERTICES ****************************************
# a "v" line looks like this:
# f x y z ...
x = float(line_elements[1])
y = float(line_elements[2])
z = float(line_elements[3])
if minX < x < maxX and minY < y < maxY and minZ < z < maxZ:
# if vertex is within the bounding box, we include it in the new OBJ file
new_obj_file.write(line)
v_keepers[str(original_v_number)] = str(new_v_number)
new_v_number = new_v_number + 1
kept_vertices = kept_vertices +1
kept_lines = kept_lines + 1
else: # if vertex is NOT in the bounding box
new_obj_file.write(line)
discarded_vertices = discarded_vertices +1
discarded_lines = discarded_lines + 1
original_v_number = original_v_number + 1
else: # line_elements[0] == "f":
# ************************ PROCESS FACES ****************************************
# a "f" line looks like this:
# f v1/vt1/vn1 v2/vt2/vn2 v3/vt3/vn3 ...
# We need to delete any face lines where ANY of the 3 vertices v1, v2 or v3 are NOT in v_keepers.
v = ["", "", ""]
# Note that v1, v2 and v3 are the first "/" separated elements within each line element.
for i in range(0,3):
v[i] = line_elements[i+1].split('/')[0]
# now we can check if EACH of these 3 vertices are in v_keepers.
# for each f line, we need to determine if all 3 vertices are in the v_keepers list
if v[0] in v_keepers and v[1] in v_keepers and v[2] in v_keepers:
new_obj_file.write(line)
kept_lines = kept_lines + 1
kept_faces = kept_faces +1
else: # at least one of the vertices in this face has been deleted, so we need to delete the face too.
discarded_lines = discarded_lines + 1
discarded_faces = discarded_faces +1
new_obj_file.write("# CROPPED "+line)
# end of line processing loop
obj_file.close()
new_obj_file.close()
print ("kept vertices: ", kept_vertices ,"discarded vertices: ", discarded_vertices)
print ("kept faces: ", kept_faces, "discarded faces: ", discarded_faces)
print ("kept lines: ", kept_lines, "discarded lines: ", discarded_lines)
Unfortunately, (at least for now) there is no way to specify the bounding box in Reality Capture API.

counting non-empty lines and sum of lengths of those lines in python

Am trying to create a function that takes a filename and it returns a 2-tuple with the number of the non-empty lines in that program, and the sum of the lengths of all those lines. Here is my current program:
def code_metric(file):
with open(file, 'r') as f:
lines = len(list(filter(lambda x: x.strip(), f)))
num_chars = sum(map(lambda l: len(re.sub('\s', '', l)), f))
return(lines, num_chars)
The result I get is get if I do:
if __name__=="__main__":
print(code_metric('cmtest.py'))
is
(3, 0)
when it should be:
(3,85)
Also is there a better way of finding the sum of the length of lines using using the functionals map, filter, and reduce? I did it for the first part but couldn't figure out the second half. AM kinda new to python so any help would be great.
Here is the test file called cmtest.py:
import prompt,math
x = prompt.for_int('Enter x')
print(x,'!=',math.factorial(x),sep='')
First line has 18 characters (including white space)
Second line has 29 characters
Third line has 38 characters
[(1, 18), (1, 29), (1, 38)]
The line count is 85 characters including white spaces. I apologize, I mis-read the problem. The length total for each line should include the whitespaces as well.
A fairly simple approach is to build a generator to strip trailing whitespace, then enumerate over that (with a start value of 1) filtering out blank lines, and summing the length of each line in turn, eg:
def code_metric(filename):
line_count = char_count = 0
with open(filename) as fin:
stripped = (line.rstrip() for line in fin)
for line_count, line in enumerate(filter(None, stripped), 1):
char_count += len(line)
return line_count, char_count
print(code_metric('cmtest.py'))
# (3, 85)
In order to count lines, maybe this code is cleaner:
with open(file) as f:
lines = len(file.readlines())
For the second part of your program, if you intend to count only non-empty characters, then you forgot to remove '\t' and '\n'. If that's the case
with open(file) as f:
num_chars = len(re.sub('\s', '', f.read()))
Some people have advised you to do both things in one loop. That is fine, but if you keep them separated you can make them into different functions and have more reusability of them that way. Unless you are handling huge files (or executing this coded millions of times), it shouldn't matter in terms of performance.