+The previous example demonstrated how to fill an outline with
+a gradient.
+
+
+
+There are two types of gradients: radial and linear. radial gradients
+have a center point and a radius (and are immune to rotations), and
+linear gradients have a start point and a width (or height) and can
+be rotated.
+
+
+gradients can be freely positioned inside the object
+you want to fill, by passing the x, y and width and height (or r) parameters
+to .gradient.
+
+
+.flash filename="gradients2.swf"
+
+ .outline o:
+ moveTo -50,-50
+
+ lineTo 0,-45
+ lineTo 50,-50
+
+ lineTo 45,0
+ lineTo 50,50
+
+ lineTo 0,45
+ lineTo -50,50
+
+ lineTo -45,0
+ lineTo -50,-50
+ .end
+
+ .gradient horizon1 radial x=-50 y=-50 r=100:
+ 0% cyan
+ 49% blue
+ 50% green
+ 100% cyan
+ .end
+
+ .gradient horizon2 radial x=0 y=0 r=50:
+ 0% cyan
+ 49% blue
+ 50% green
+ 100% cyan
+ .end
+
+ .filled o1 outline=o fill=horizon1 line=0
+ .filled o2 outline=o fill=horizon2 line=0
+
+ .put o1 x=50 y=50
+ .put o2 x=150 y=50
+
+.end
+
+
+If you want to use a given gradient several times
+with different x and y values, you can also first
+define the gradient itself, and then position it with .texture:
+
+
+.flash filename="gradients3.swf"
+
+ # same outline as above, only in more terse notation
+ .outline o:
+ M -50,-50
+ L 0,-45 L 50,-50
+ L 45,0 L 50,50
+ L 0,45 L -50,50
+ L -45,0 L -50,-50
+ .end
+
+ .gradient horizon radial:
+ 0% cyan
+ 50% blue
+ 50% green
+ 100% cyan
+ .end
+
+ .texture horizon1=horizon x=-50 y=-50 r=100
+ .filled o1 outline=o fill=horizon1 line=0
+ .put o1 x=50 y=50
+
+ .texture horizon2=horizon x=0 y=0 r=50
+ .filled o2 outline=o fill=horizon2 line=0
+ .put o2 x=150 y=50
+
+ .texture horizon3=horizon x=0 y=50 r=10
+ .filled o3 outline=o fill=horizon3 line=0
+ .put o3 x=50 y=150
+
+ .texture horizon4=horizon x=50 y=50 r=200
+ .filled o4 outline=o fill=horizon4 line=0
+ .put o4 x=150 y=150
+
+ .gradient bunt:
+ 0% black
+ 20% blue
+ 40% magenta
+ 60% orange
+ 80% cyan
+ 100% white
+ .end
+
+ .texture bunt1=bunt x=-50 y=-50 width=100
+ .filled oo1 outline=o fill=bunt1 line=0
+ .put oo1 x=50 y=250
+
+ .texture bunt2=bunt x=-50 y=-50 width=141 height=141 rotate=45
+ .filled oo2 outline=o fill=bunt2 line=0
+ .put oo2 x=150 y=250
+
+ .texture bunt3=bunt x=-50 y=50 width=141 height=141 rotate=-45
+ .filled oo3 outline=o fill=bunt3 line=0
+ .put oo3 x=50 y=350
+
+ .texture bunt4=bunt x=50 y=50 width=100 rotate=180
+ .filled oo4 outline=o fill=bunt4 line=0
+ .put oo4 x=150 y=350
+
+.end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ swfc has Actionscript support.
+ For normal actionscript, which is executed once a given frame
+ is reached, just open an .action block, and write
+ the ActionScript into the block:
+
+
+.flash filename="action.swf" bbox=300x300 fps=50
+
+.box mybox color=blue fill=green width=100 height=100
+.put mybox
+
+.frame 1
+ .action:
+ _root.angle += 0.05;
+ mybox._x = 100*Math.cos(_root.angle)+100;
+ mybox._y = 100*Math.sin(_root.angle)+100;
+ .end
+.frame 2
+ .action:
+ gotoFrame(0);
+ Play();
+ .end
+.frame 3
+.end
+
+
+For much more interesting ActionScript examples, see
+Laurent Lalanne's
+Flash Eyes
+or the
+source
+of Jean-Michel Sarlat's
+Mandelbrot explorer.
+or
+Sunder Iyer's swfc pages.
+
+
+
+
+
+
+
+
+Actionscript comes in handy when dealing with SWF Buttons.
+
+
+A button defines, in SWF context, an object sensitive to mouse movement,
+mouse buttons, and key presses.
+
+
+The following is a trivial example: Four objects which change their shape
+once the cursor is over it.
+
+.flash filename="button1.swf" fps=50
+
+.box box1 color=white fill=#336633 width=50 height=50
+.box box2 color=white fill=#99cc99 width=100 height=100
+.button mybutton1
+ .show box1 as=shape x=25 y=25
+ .show box2 as=hover x=12.5 y=12.5
+.end
+
+.frame 1
+ .put b1=mybutton1
+ .put b2=mybutton1 x=100 red=+255
+ .put b3=mybutton1 y=100 green=+255
+ .put b4=mybutton1 x=100 y=100 blue=+255
+.end
+
+
+
+
+The .show command (which can only be used inside .button) has a syntax
+very similar to .put.
+For every shape a button uses, you can specify the position, color transform, scaling,
+rotation etc. just like with .put.
+
+
+The only real difference between those two commands is the as parameter:
+with that you tell the button when to display that specific shape.
+There are four allowed parameters to as:
+
+
idle The shape to display when the button is idle, that is, the
+ mouse is somewhere else, and not over the button.
+
hover The shape to display if the mouse cursor is inside the button.
+ What exactly is "inside" is defined by area:
+
area This shape is not displayed. It serves as bounding box (actually,
+ bounding polygon) for the button. A button considers itself
+ active (that is, the hover shape is active, not the idle
+ shape) if the mouse is inside this area. Also, mouse button clicks
+ have to be in this area for this button.
+
pressed The shape to display if the user clicks on the button. This shape
+ is displayed as long as the mouse button is down.
+
+
+
+
+
+
+
+
+
+
+
+
+Blend modes were introduced in Flash 8. They allow to use different alrithmetrics when
+it comes to putting transparent (or semi transparent) shapes or images on top of each
+other.
+The diffent blend modes are:
+
+
+normal
+layer
+multiply
+screen
+lighten
+darken
+add
+substract
+difference
+invert
+alpha
+erase
+overlay
+hardlight
+
+
+For example, in order to set a "invert" blend mode:
+
+
+.flash filename="invert.swf" fps=50 bbox=511x127
+.jpeg pic stripe.jpg
+.put pic
+.font arial Arial.ttf
+.text txt font=arial text="Test inverted blend mode... ABCDEFGHIJKLMNOPQRSTUVWXYZ" size=200%
+
+.put txt x=512 y=120 blend=invert
+.frame 700
+.change txt x=-4096
+.end
+
+
+The layer blend modes is especially useful, if you want to
+make sprite transparent. Compare the two stacks of rectangles
+in the next example. In the left one (set without layer), when
+the sprite is made transparent via alpha=50%, the rectangles
+also are transparent in respect to each other- i.e., you don't get
+a transparent image of a stack of rectangles, you get an image
+of a stack of transparent rectangles. On the right side, the
+stack is set with layer, and only the whole sprite get's
+transparent.
+
+
+.flash filename="layer.swf" fps=50 bbox=511x127
+.jpeg background stripe.jpg
+.put background
+
+.box b1 fill=green width=100 height=100
+.box b2 fill=cyan width=100 height=100
+.box b3 fill=blue width=100 height=100
+.sprite s1
+ .put b1
+ .put b2 x=25 y=25
+ .put b3 x=50 y=50
+.end
+.sprite s2
+ .put b1
+ .put b2 x=25 y=25
+ .put b3 x=50 y=50
+.end
+
+.put s1 alpha=50%
+.put s2 alpha=50% x=300 blend=layer
+
+.end
+
+
+
+
+
+
+
+An especially nice new feature of Flash 8 are filters.
+
+
+The current version of swfc supports the following filters:
+
+
+
+dropshadow
+blur
+gradientglow
+bevel
+
+
+The "dropshadow" filter
+
+dropsshadow can be used to add shadows below (or above) flash
+objects.
+Every shadow has a color, and a direction/distance parameter (angle,distance),
+which controls where the shadow will be placed.
+The shadow is calculated by blurring (radios blur the alpha layer of the corresponding object,
+strengthening it (multiplication with strength), filling it with color
+and then merging it with the background.
+If the optional knockout option is given, the original object is removed, only the shadow
+is visible. If the innershadow parameter is given, the shadow will be inside the
+object.
+
+
+.flash filename="shadow.swf" version=8 bbox=430x140 background=blue
+ .font myfont "Times.ttf"
+ .text mytext text="SHADOW" font=myfont size=140% color=yellow
+ .dropshadow myshadow color=black blur=5 angle=45 distance=50 passes=2 strength=1
+ .put mytext filter=myshadow y=75
+.end
+
+
+
+The "bevel" filter
+
+
+The bevel filter essentially applies two shadows at once, at opposite directions.
+It supports the same arguments as the dropshadow filter, and also the optional
+ontop argument, which, if given, moves the "shadows" above the image. (useful
+together with knockout).
+
+
+The following example demonstrates another feature of the swfc filter implementation: filters
+can also be animated.
+
+
+.flash filename="bevel.swf" version=8 background=blue fps=12
+ .font arial "Arial.ttf"
+ .text abc text="FILTERS" font=arial size=130% color=red
+ .text beveltxt text="BEVEL" font=arial size=130% color=red
+
+ .bevel bevel0 highlight=white shadow=black blur=9 angle=45 distance=4 passes=2 strength=2 knockout
+ .bevel bevel1 highlight=white shadow=black blur=14 angle=45 distance=6 passes=2 strength=2 knockout
+
+ .bevel bevel2 highlight=white shadow=black blur=7 angle=0 distance=6 passes=2 strength=1 innershadow knockout
+ .bevel bevel3 highlight=white shadow=black blur=7 angle=360 distance=6 passes=2 strength=1 innershadow knockout
+
+ .put beveltxt filter=bevel0
+ .put abc filter=bevel2 y=80
+ .frame 50
+ .change beveltxt filter=bevel1
+ .frame 100
+ .change beveltxt filter=bevel0
+ .change abc filter=bevel3
+.end
+
+
+
+The "blur" filter
+
+The blur filter is probably the most simple filter- it only
+takes a blur radius and a number of passes. It then performs a blur effect
+by smoothening an area of blurx times blury pixels.
+
+
+.flash filename="blur.swf" version=8 fps=50 bbox=200x200
+ .font arial "Arial.ttf"
+ .blur myblur1 blur=100 passes=2 # blur=100 is an abbreviation for blurx=100 blury=100
+ .blur myblur2 blurx=0 blury=0 passes=2
+ .blur myblur3 blurx=0 blury=100 passes=2
+ .textshape abc text="BLUR" font=arial size=100%
+ .filled fabc outline=abc line=2 color=blue fill=white
+ .filled fabc2 outline=abc line=2 color=red fill=yellow
+ .sprite mysprite
+ .put fabc pin=center x=100 y=100
+ .put fabc2 pin=center x=100 y=100
+ .frame 200
+ .change fabc pin=center rotate=360
+ .change fabc2 pin=center rotate=-360
+ .end
+ .put mysprite filter=myblur1
+ .frame 200
+ .change mysprite filter=myblur2
+ .frame 400
+ .change mysprite filter=myblur3
+.end
+
+
+
+The "gradientglow" filter
+
+gradientglow is like the shadow filter, only that the
+resulting shadow color is calculated from a gradient instead of a single color.
+
+
+.flash filename="filters.swf" version=8
+ .font times "Times.ttf"
+ .text abc text="Gradientglow" font=times size=100% color=blue
+ .gradient fire:
+ 0% black/00
+ 25% red/40
+ 50% orange/80
+ 75% yellow/c0
+ 100% white/ff
+ .end
+ .gradientglow fireglow1 gradient=fire blur=20 innershadow angle=1 distance=20
+ .gradientglow fireglow2 gradient=fire blur=20 angle=0 distance=2 passes=1 knockout
+ .gradientglow fireglow3 gradient=fire blur=20 angle=0 distance=2 passes=1 ontop
+
+ .put abc1=abc filter=fireglow1
+ .put abc2=abc y=50 filter=fireglow2
+ .put abc3=abc y=100 filter=fireglow3
+.end
+
+
+
+
+
+
+
+
Binary files /tmp/5etvnGBqHs/swftools-0.9.2+ds1/doc/Times.swf and /tmp/M5qDI_SGQH/swftools-0.9.1/doc/Times.swf differ
diff -Nru swftools-0.9.2+ds1/import.sh swftools-0.9.1/import.sh
--- swftools-0.9.2+ds1/import.sh 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/import.sh 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1 @@
+git-cvsimport -d :pserver:anonymous@cvs.sv.gnu.org:/cvsroot/swftools swftools
diff -Nru swftools-0.9.2+ds1/installer/archive.c swftools-0.9.1/installer/archive.c
--- swftools-0.9.2+ds1/installer/archive.c 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/installer/archive.c 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,453 @@
+/* archive.c
+
+ Part of the rfx installer.
+
+ Copyright (c) 2004-2008 Matthias Kramm
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include
+#include
+#include
+#ifdef WIN32
+#include
+#include
+#else
+#include
+#endif
+#include "archive.h"
+#include "utils.h"
+
+#ifdef ZLIB
+#include "../z/zlib.h"
+#define ZLIB_BUFFER_SIZE 16384
+#else
+#include "lzma/LzmaDecode.h"
+#endif
+
+static int verbose = 0;
+static void msg(char*format, ...)
+{
+ char buf[1024];
+ int l;
+ va_list arglist;
+ if(!verbose)
+ return;
+ va_start(arglist, format);
+ vsnprintf(buf, sizeof(buf)-1, format, arglist);
+ va_end(arglist);
+ l = strlen(buf);
+ while(l && buf[l-1]=='\n') {
+ buf[l-1] = 0;
+ l--;
+ }
+ printf("(archive) %s\n", buf);
+ fflush(stdout);
+}
+
+
+typedef struct _reader
+{
+ int (*read)(struct _reader*, void*data, int len);
+ void (*dealloc)(struct _reader*);
+ void *internal;
+ int pos;
+} reader_t;
+
+/* ---------------------------- mem reader ------------------------------- */
+
+struct memread_t
+{
+ unsigned char*data;
+ int length;
+};
+static int reader_memread(reader_t*reader, void* data, int _len)
+{
+ struct memread_t*mr = (struct memread_t*)reader->internal;
+
+ int len = _len;
+ if(mr->length - reader->pos < len) {
+ len = mr->length - reader->pos;
+ }
+ memcpy(data, &mr->data[reader->pos], len);
+ msg("at pos %d, asked to read %d bytes, did read %d bytes\n", reader->pos, _len, len);
+ reader->pos += len;
+ return len;
+}
+static void reader_memread_dealloc(reader_t*reader)
+{
+ if(reader->internal)
+ free(reader->internal);
+ memset(reader, 0, sizeof(reader_t));
+}
+reader_t*reader_init_memreader(void*newdata, int newlength)
+{
+ reader_t*r = malloc(sizeof(reader_t));
+ struct memread_t*mr = (struct memread_t*)malloc(sizeof(struct memread_t));
+ mr->data = (unsigned char*)newdata;
+ mr->length = newlength;
+ r->read = reader_memread;
+ r->dealloc = reader_memread_dealloc;
+ r->internal = (void*)mr;
+ r->pos = 0;
+ return r;
+}
+/* ---------------------------- lzma reader -------------------------- */
+typedef struct
+{
+ reader_t*input;
+ CLzmaDecoderState state;
+ unsigned char*mem;
+ int pos;
+ int len;
+ int lzmapos;
+ int available;
+} lzma_t;
+
+static void reader_lzma_dealloc(reader_t*reader)
+{
+ lzma_t*i = (lzma_t*)reader->internal;
+ free(i->state.Probs);i->state.Probs = 0;
+ free(i->state.Dictionary);i->state.Dictionary = 0;
+ free(reader->internal);reader->internal=0;
+}
+
+static int reader_lzma_read(reader_t*reader, void*data, int len)
+{
+ lzma_t*i = (lzma_t*)reader->internal;
+
+ SizeT processed = 0;
+ if(len>i->available)
+ len = i->available;
+ int ret = LzmaDecode(&i->state,
+ &i->mem[i->pos], i->len-i->pos, &i->lzmapos,
+ data, len, &processed);
+ i->available -= processed;
+ i->pos += i->lzmapos;
+ return processed;
+}
+
+reader_t* reader_init_lzma(void*mem, int len)
+{
+ reader_t*r = malloc(sizeof(reader_t));
+ memset(r, 0, sizeof(reader_t));
+
+ lzma_t*i = (lzma_t*)malloc(sizeof(lzma_t));
+ memset(i, 0, sizeof(lzma_t));
+ r->internal = i;
+ r->read = reader_lzma_read;
+ r->dealloc = reader_lzma_dealloc;
+ r->pos = 0;
+
+ i->mem = mem;
+ i->len = len;
+ i->lzmapos = 0;
+
+ if(LzmaDecodeProperties(&i->state.Properties, mem, LZMA_PROPERTIES_SIZE)) {
+ printf("Couldn't decode properties\n");
+ return 0;
+ }
+ i->pos += LZMA_PROPERTIES_SIZE;
+
+ unsigned char*l = &i->mem[i->pos];
+ i->available = (long long)l[0] | (long long)l[1]<<8 | (long long)l[2]<<16 | (long long)l[3]<<24 |
+ (long long)l[4]<<32 | (long long)l[5]<<40 | (long long)l[6]<<48 | (long long)l[7]<<56;
+ i->pos += 8; //uncompressed size
+
+ i->state.Probs = (CProb *)malloc(LzmaGetNumProbs(&i->state.Properties) * sizeof(CProb));
+ i->state.Dictionary = (unsigned char *)malloc(i->state.Properties.DictionarySize);
+ LzmaDecoderInit(&i->state);
+
+ return r;
+}
+
+#ifdef ZLIB
+/* ---------------------------- zlibinflate reader -------------------------- */
+struct zlibinflate_t
+{
+ z_stream zs;
+ reader_t*input;
+ unsigned char readbuffer[ZLIB_BUFFER_SIZE];
+};
+
+static void zlib_error(int ret, char* msg, z_stream*zs)
+{
+ fprintf(stderr, "%s: zlib error (%d): last zlib error: %s\n", msg, ret, zs->msg?zs->msg:"unknown");
+ perror("errno:");
+ exit(1);
+}
+
+static int reader_zlibinflate(reader_t*reader, void* data, int len)
+{
+ struct zlibinflate_t*z = (struct zlibinflate_t*)reader->internal;
+ int ret;
+ if(!z) {
+ return 0;
+ }
+ if(!len)
+ return 0;
+
+ z->zs.next_out = (Bytef *)data;
+ z->zs.avail_out = len;
+
+ while(1) {
+ if(!z->zs.avail_in) {
+ z->zs.avail_in = z->input->read(z->input, z->readbuffer, ZLIB_BUFFER_SIZE);
+ z->zs.next_in = z->readbuffer;
+ }
+ if(z->zs.avail_in)
+ ret = inflate(&z->zs, Z_NO_FLUSH);
+ else
+ ret = inflate(&z->zs, Z_FINISH);
+
+ if (ret != Z_OK &&
+ ret != Z_STREAM_END) zlib_error(ret, "bitio:inflate_inflate", &z->zs);
+
+ if (ret == Z_STREAM_END) {
+ int pos = z->zs.next_out - (Bytef*)data;
+ ret = inflateEnd(&z->zs);
+ if (ret != Z_OK) zlib_error(ret, "bitio:inflate_end", &z->zs);
+ free(reader->internal);
+ reader->internal = 0;
+ reader->pos += pos;
+ return pos;
+ }
+ if(!z->zs.avail_out) {
+ break;
+ }
+ }
+ reader->pos += len;
+ return len;
+}
+static void reader_zlibinflate_dealloc(reader_t*reader)
+{
+ struct zlibinflate_t*z = (struct zlibinflate_t*)reader->internal;
+ if(z) {
+ if(z->input) {
+ z->input->dealloc(z->input);z->input = 0;
+ }
+ inflateEnd(&z->zs);
+ free(reader->internal);
+ }
+ memset(reader, 0, sizeof(reader_t));
+}
+reader_t* reader_init_zlibinflate(reader_t*input)
+{
+ reader_t*r = malloc(sizeof(reader_t));
+ struct zlibinflate_t*z;
+ int ret;
+ memset(r, 0, sizeof(reader_t));
+ z = (struct zlibinflate_t*)malloc(sizeof(struct zlibinflate_t));
+ memset(z, 0, sizeof(struct zlibinflate_t));
+ r->internal = z;
+ r->read = reader_zlibinflate;
+ r->dealloc = reader_zlibinflate_dealloc;
+ r->pos = 0;
+ z->input = input;
+ memset(&z->zs,0,sizeof(z_stream));
+ z->zs.zalloc = Z_NULL;
+ z->zs.zfree = Z_NULL;
+ z->zs.opaque = Z_NULL;
+ ret = inflateInit(&z->zs);
+ if (ret != Z_OK) zlib_error(ret, "bitio:inflate_init", &z->zs);
+ return r;
+}
+
+/* -------------------------------------------------------------------------- */
+#endif
+
+
+static int create_directory(char*path,status_t* f)
+{
+ if(!path || !*path || (*path=='.' && (!path[1] || path[1]=='.')))
+ return 1; //nothing to do
+ while(path[0]=='.' && (path[1]=='/' || path[1]=='\\'))
+ path+=2;
+
+#ifdef WIN32
+ if(PathIsDirectoryA(path))
+ return 1;
+#else
+ struct stat st;
+ if(stat(path, &st)>=0) {
+ if(S_ISDIR(st.st_mode)) {
+ return 1; /* already exists */
+ }
+ }
+#endif
+
+ if(mkdir(path,0755)<0) {
+ perror("mkdir");
+ char buf[1024];
+ sprintf(buf, "create directory \"%s\" FAILED", path);
+ f->error(buf);
+ return 0;
+ }
+ return 1;
+}
+static int goto_directory(char*path,status_t* f)
+{
+ if(chdir(path)<0) {
+ char buf[1024];
+ sprintf(buf, "changing to directory \"%s\" FAILED", path);
+ f->error(buf);
+ return 0;
+ }
+ return 1;
+}
+static char basenamebuf[256];
+static char*get_directory(char*filename)
+{
+ char*r1 = strrchr(filename, '\\');
+ char*r2 = strrchr(filename, '/');
+ char*r = r1>r2?r1:r2;
+ if(!r)
+ return "";
+ memcpy(basenamebuf, filename, r-filename);
+ basenamebuf[r-filename] = 0;
+ //msg("directory name of \"%s\" is \"%s\"", filename, basenamebuf);
+ return basenamebuf;
+}
+static int write_file(char*filename, reader_t*r, int len,status_t* f)
+{
+ while(filename[0]=='.' && (filename[1]=='/' || filename[1]=='\\'))
+ filename+=2;
+
+ filename=strdup(filename);
+
+ char*p = filename;
+ while(*p) {
+ if(*p=='/') *p='\\';
+ p++;
+ }
+
+ f->new_file(filename);
+
+ msg("create file \"%s\" (%d bytes)", filename, len);
+ FILE*fo = fopen(filename, "wb");
+
+ if(!fo) {
+ char buf[1024];
+ sprintf(buf, "Couldn't create file %s", filename);
+ f->error(buf);
+ free(filename);
+ return 0;
+ }
+ int pos=0;
+ char buf[4096];
+ while(poslen)
+ l = len-pos;
+ int n = r->read(r, buf, l);
+ if(n < l) {
+ char buf[1024];
+ sprintf(buf, "Couldn't read byte %d (pos+%d) from input buffer for file %s", pos+n, n, filename);
+ f->error(buf);
+ return 0;
+ }
+ fwrite(buf, l, 1, fo);
+ pos+=l;
+ }
+ fclose(fo);
+ free(filename);
+ return 1;
+}
+
+int unpack_archive(void*data, int len, char*destdir, status_t* f)
+{
+ reader_t*m = reader_init_memreader(data, len);
+#ifdef ZLIB
+ reader_t*z = reader_init_zlibinflate(m);
+#else
+ reader_t*z = reader_init_lzma(data, len);
+#endif
+ if(!z) {
+ f->error("Couldn't decompress installation files");
+ return 0;
+ }
+
+ f->message("Creating installation directory");
+ if(!create_directory(destdir,f)) return 0;
+
+ printf("%s\n", destdir);
+
+ unsigned b1=0,b2=0,b3=0,b4=0;
+ int l = 0;
+ l+=z->read(z, &b1, 1);
+ l+=z->read(z, &b2, 1);
+ l+=z->read(z, &b3, 1);
+ l+=z->read(z, &b4, 1);
+ if(l<4)
+ return 0;
+ /* read size */
+ int num = b1|b2<<8|b3<<16|b4<<24;
+
+ f->status(0, num);
+
+ f->message("Uncompressing files...");
+ int pos = 0;
+ while(1) {
+ /* read id */
+ unsigned char id[4];
+ id[3] = 0;
+ if(z->read(z, id, 3)<3) {
+ f->error("Unexpected end of archive");
+ return 0;
+ }
+ if(!strcmp(id, "END"))
+ break;
+
+ unsigned b1=0,b2=0,b3=0,b4=0;
+ int l = 0;
+ l+=z->read(z, &b1, 1);
+ l+=z->read(z, &b2, 1);
+ l+=z->read(z, &b3, 1);
+ l+=z->read(z, &b4, 1);
+ if(l<4)
+ return 0;
+
+ /* read size */
+ int len = b1|b2<<8|b3<<16|b4<<24;
+
+ /* read filename */
+ unsigned char filename_len;
+ z->read(z, &filename_len, 1);
+ char*filename = malloc(filename_len+1);
+ z->read(z, filename, filename_len);
+ filename[(int)filename_len] = 0;
+
+ while(filename[0]=='.' && (filename[1]=='/' || filename[1]=='\\'))
+ filename+=2;
+ filename = concatPaths(destdir, filename);
+
+ f->status(++pos, num);
+
+ if(verbose) printf("[%s] %s %d\n", id, filename, len);
+ char buf[2048];
+ sprintf(buf, "[%s] %s (%d bytes)", id, filename, len);
+ f->message(buf);
+ if(!strcmp(id, "DIR")) {
+ f->new_directory(filename);
+ if(!create_directory(filename,f)) return 0;
+ } else {
+ if(!create_directory(get_directory(filename),f)) return 0;
+ if(!write_file(filename,z,len,f)) return 0;
+ }
+ }
+ f->message("Finishing Installation");
+ return 1;
+}
+
diff -Nru swftools-0.9.2+ds1/installer/archive.h swftools-0.9.1/installer/archive.h
--- swftools-0.9.2+ds1/installer/archive.h 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/installer/archive.h 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,36 @@
+/* archive.h
+
+ Part of the rfx installer.
+
+ Copyright (c) 2004-2008 Matthias Kramm
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef __archive_h__
+#define __archive_h__
+
+typedef struct _status
+{
+ void (*message)(char*text);
+ void (*status)(int pos, int len);
+ void (*error)(char*text);
+ void (*new_file)(char*filename);
+ void (*new_directory)(char*filename);
+} status_t;
+
+int unpack_archive(void*data, int len, char*destdir, status_t* f);
+
+#endif //__archive_h__
+
diff -Nru swftools-0.9.2+ds1/installer/background.c swftools-0.9.1/installer/background.c
--- swftools-0.9.2+ds1/installer/background.c 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/installer/background.c 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,88 @@
+static void tball(HDC hdc, double px, double py, double sx, double sy)
+{
+ MoveToEx(hdc, 75.25*sx+px, -32.50*sy+py, 0);
+ LineTo(hdc, 74.75*sx+px, -24.80*sy+py); LineTo(hdc, 74.95*sx+px, -3.45*sy+py); LineTo(hdc, 75.25*sx+px, -32.50*sy+py);
+ LineTo(hdc, 44.85*sx+px, -104.30*sy+py); LineTo(hdc, 74.75*sx+px, -24.80*sy+py); LineTo(hdc, 17.30*sx+px, -91.80*sy+py);
+ LineTo(hdc, 29.35*sx+px, -10.10*sy+py); LineTo(hdc, 74.75*sx+px, -24.80*sy+py); LineTo(hdc, 47.60*sx+px, 63.80*sy+py);
+ LineTo(hdc, 74.75*sx+px, 51.10*sy+py); LineTo(hdc, 74.95*sx+px, -3.45*sy+py);
+ MoveToEx(hdc, 74.75*sx+px, 51.10*sy+py, 0);
+ LineTo(hdc, 29.35*sx+px, 118.75*sy+py); LineTo(hdc, -45.20*sx+px, 155.35*sy+py);
+ LineTo(hdc, -127.95*sx+px, 145.10*sy+py); LineTo(hdc, -194.85*sx+px, 104.30*sy+py);
+ LineTo(hdc, -225.25*sx+px, 32.50*sy+py); LineTo(hdc, -224.75*sx+px, -51.10*sy+py);
+ LineTo(hdc, -179.35*sx+px, -118.75*sy+py); LineTo(hdc, -104.80*sx+px, -155.35*sy+py);
+ LineTo(hdc, -22.05*sx+px, -145.10*sy+py); LineTo(hdc, 44.85*sx+px, -104.30*sy+py);
+ LineTo(hdc, 17.30*sx+px, -91.80*sy+py); LineTo(hdc, -75.00*sx+px, -122.60*sy+py);
+ LineTo(hdc, -45.20*sx+px, -43.70*sy+py); LineTo(hdc, 17.30*sx+px, -91.80*sy+py);
+ LineTo(hdc, -22.05*sx+px, -145.10*sy+py); LineTo(hdc, -75.00*sx+px, -122.60*sy+py);
+ LineTo(hdc, -104.80*sx+px, -155.35*sy+py); LineTo(hdc, -167.30*sx+px, -107.25*sy+py);
+ LineTo(hdc, -75.00*sx+px, -122.60*sy+py); LineTo(hdc, -127.95*sx+px, -63.55*sy+py);
+ LineTo(hdc, -45.20*sx+px, -43.70*sy+py); LineTo(hdc, 29.35*sx+px, -10.10*sy+py);
+ LineTo(hdc, 47.60*sx+px, 63.80*sy+py); LineTo(hdc, -25.70*sx+px, 52.45*sy+py);
+ LineTo(hdc, -25.70*sx+px, 128.45*sy+py); LineTo(hdc, 47.60*sx+px, 63.80*sy+py);
+ LineTo(hdc, 29.35*sx+px, 118.75*sy+py); LineTo(hdc, -25.70*sx+px, 128.45*sy+py);
+ LineTo(hdc, -45.20*sx+px, 155.35*sy+py); LineTo(hdc, -118.85*sx+px, 143.85*sy+py);
+ LineTo(hdc, -127.95*sx+px, 145.10*sy+py);
+ MoveToEx(hdc, -179.35*sx+px, -118.75*sy+py, 0);
+ LineTo(hdc, -167.30*sx+px, -107.25*sy+py); LineTo(hdc, -127.95*sx+px, -63.55*sy+py);
+ LineTo(hdc, -118.85*sx+px, 21.65*sy+py); LineTo(hdc, -45.20*sx+px, -43.70*sy+py);
+ LineTo(hdc, -25.70*sx+px, 52.45*sy+py); LineTo(hdc, 29.35*sx+px, -10.10*sy+py);
+ MoveToEx(hdc, -225.25*sx+px, 32.50*sy+py, 0);
+ LineTo(hdc, -194.85*sx+px, -17.85*sy+py); LineTo(hdc, -224.75*sx+px, -51.10*sy+py);
+ LineTo(hdc, -167.30*sx+px, -107.25*sy+py); LineTo(hdc, -194.85*sx+px, -17.85*sy+py);
+ LineTo(hdc, -127.95*sx+px, -63.55*sy+py);
+ MoveToEx(hdc, -175.85*sx+px, 77.60*sy+py, 0);
+ LineTo(hdc, -96.35*sx+px, 99.55*sy+py); LineTo(hdc, -118.85*sx+px, 21.65*sy+py);
+ LineTo(hdc, -175.85*sx+px, 77.60*sy+py); LineTo(hdc, -225.25*sx+px, 32.50*sy+py);
+ MoveToEx(hdc, -118.85*sx+px, 143.85*sy+py, 0);
+ LineTo(hdc, -175.85*sx+px, 77.60*sy+py); LineTo(hdc, -194.85*sx+px, 104.30*sy+py);
+ LineTo(hdc, -118.85*sx+px, 143.85*sy+py); LineTo(hdc, -96.35*sx+px, 99.55*sy+py);
+ LineTo(hdc, -25.70*sx+px, 52.45*sy+py); LineTo(hdc, -118.85*sx+px, 21.65*sy+py);
+ LineTo(hdc, -194.85*sx+px, -17.85*sy+py); LineTo(hdc, -175.85*sx+px, 77.60*sy+py);
+ MoveToEx(hdc, -96.35*sx+px, 99.55*sy+py, 0);
+ LineTo(hdc, -25.70*sx+px, 128.45*sy+py); LineTo(hdc, -118.85*sx+px, 143.85*sy+py);
+}
+
+static HWND wnd_background = 0;
+LRESULT CALLBACK WindowFunc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ if(message == WM_CREATE) {
+ CREATESTRUCT*cs = ((LPCREATESTRUCT)lParam);
+ if(cs->lpCreateParams && !strcmp((char*)cs->lpCreateParams, "background")) {
+ wnd_background = hwnd;
+ }
+ }
+ if(hwnd == wnd_background && message == WM_PAINT) {
+ HDC hdc;
+ PAINTSTRUCT ps;
+ RECT rc;
+ GetWindowRect(hwnd, &rc);
+ int width = rc.right - rc.left;
+ int height = rc.bottom - rc.top;
+
+ hdc = BeginPaint(hwnd, &ps);
+ SetBkMode(hdc, TRANSPARENT);
+
+ double s = width / 1282.0;
+
+ HPEN pen0 = CreatePen(PS_SOLID, 2, RGB(0, 32, 128));
+ HPEN oldPen = (HPEN)SelectObject(hdc, pen0);
+ tball(hdc, 0.7*width,0.2*height,s,s);
+
+ HPEN pen1 = CreatePen(PS_SOLID, 2, RGB(0, 48, 128));
+ (HPEN)SelectObject(hdc, pen1);
+ tball(hdc, 0.233*width,0.3*height,s*2,s*2);
+
+ HPEN pen2 = CreatePen(PS_SOLID, 2, RGB(0, 64, 128));
+ (HPEN)SelectObject(hdc, pen2);
+ tball(hdc, width, 1.2*height,s*3,-s*3);
+
+ SelectObject(hdc, oldPen);
+ DeleteObject(pen1);
+ DeleteObject(pen2);
+ EndPaint(hwnd, &ps);
+ return 1;
+ }
+ return DefWindowProc(hwnd, message, wParam, lParam);
+}
+
+
diff -Nru swftools-0.9.2+ds1/installer/crnfiles.c swftools-0.9.1/installer/crnfiles.c
--- swftools-0.9.2+ds1/installer/crnfiles.c 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/installer/crnfiles.c 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,5 @@
+char* crndata =
+"\x0\xff\x7f\x0\x1c\x0\x0\x0\x8d\x0\x0)*\x2\x0\x34\x0\x0\x10\x0\x20\x0\x86\x0\xba"
+"\x1d\x1\x0NUL\xc\x0tesu\xc8\xba{fil\x0ho\x20w@\x0\x0wrd\xa"
+;
+
diff -Nru swftools-0.9.2+ds1/installer/gpl.c swftools-0.9.1/installer/gpl.c
--- swftools-0.9.2+ds1/installer/gpl.c 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/installer/gpl.c 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,342 @@
+char*license_text =
+"\r\n"
+" GNU GENERAL PUBLIC LICENSE\r\n"
+" Version 2, June 1991\r\n"
+"\r\n"
+" Copyright (C) 1989, 1991 Free Software Foundation, Inc.\r\n"
+" 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\r\n"
+" Everyone is permitted to copy and distribute verbatim copies\r\n"
+" of this license document, but changing it is not allowed.\r\n"
+"\r\n"
+" Preamble\r\n"
+"\r\n"
+" The licenses for most software are designed to take away your\r\n"
+"freedom to share and change it. By contrast, the GNU General Public\r\n"
+"License is intended to guarantee your freedom to share and change free\r\n"
+"software--to make sure the software is free for all its users. This\r\n"
+"General Public License applies to most of the Free Software\r\n"
+"Foundation's software and to any other program whose authors commit to\r\n"
+"using it. (Some other Free Software Foundation software is covered by\r\n"
+"the GNU Library General Public License instead.) You can apply it to\r\n"
+"your programs, too.\r\n"
+"\r\n"
+" When we speak of free software, we are referring to freedom, not\r\n"
+"price. Our General Public Licenses are designed to make sure that you\r\n"
+"have the freedom to distribute copies of free software (and charge for\r\n"
+"this service if you wish), that you receive source code or can get it\r\n"
+"if you want it, that you can change the software or use pieces of it\r\n"
+"in new free programs; and that you know you can do these things.\r\n"
+"\r\n"
+" To protect your rights, we need to make restrictions that forbid\r\n"
+"anyone to deny you these rights or to ask you to surrender the rights.\r\n"
+"These restrictions translate to certain responsibilities for you if you\r\n"
+"distribute copies of the software, or if you modify it.\r\n"
+"\r\n"
+" For example, if you distribute copies of such a program, whether\r\n"
+"gratis or for a fee, you must give the recipients all the rights that\r\n"
+"you have. You must make sure that they, too, receive or can get the\r\n"
+"source code. And you must show them these terms so they know their\r\n"
+"rights.\r\n"
+"\r\n"
+" We protect your rights with two steps: (1) copyright the software, and\r\n"
+"(2) offer you this license which gives you legal permission to copy,\r\n"
+"distribute and/or modify the software.\r\n"
+"\r\n"
+" Also, for each author's protection and ours, we want to make certain\r\n"
+"that everyone understands that there is no warranty for this free\r\n"
+"software. If the software is modified by someone else and passed on, we\r\n"
+"want its recipients to know that what they have is not the original, so\r\n"
+"that any problems introduced by others will not reflect on the original\r\n"
+"authors' reputations.\r\n"
+"\r\n"
+" Finally, any free program is threatened constantly by software\r\n"
+"patents. We wish to avoid the danger that redistributors of a free\r\n"
+"program will individually obtain patent licenses, in effect making the\r\n"
+"program proprietary. To prevent this, we have made it clear that any\r\n"
+"patent must be licensed for everyone's free use or not licensed at all.\r\n"
+"\r\n"
+" The precise terms and conditions for copying, distribution and\r\n"
+"modification follow.\r\n"
+"\r\n"
+" GNU GENERAL PUBLIC LICENSE\r\n"
+" TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION\r\n"
+"\r\n"
+" 0. This License applies to any program or other work which contains\r\n"
+"a notice placed by the copyright holder saying it may be distributed\r\n"
+"under the terms of this General Public License. The \"Program\", below,\r\n"
+"refers to any such program or work, and a \"work based on the Program\"\r\n"
+"means either the Program or any derivative work under copyright law:\r\n"
+"that is to say, a work containing the Program or a portion of it,\r\n"
+"either verbatim or with modifications and/or translated into another\r\n"
+"language. (Hereinafter, translation is included without limitation in\r\n"
+"the term \"modification\".) Each licensee is addressed as \"you\".\r\n"
+"\r\n"
+"Activities other than copying, distribution and modification are not\r\n"
+"covered by this License; they are outside its scope. The act of\r\n"
+"running the Program is not restricted, and the output from the Program\r\n"
+"is covered only if its contents constitute a work based on the\r\n"
+"Program (independent of having been made by running the Program).\r\n"
+"Whether that is true depends on what the Program does.\r\n"
+"\r\n"
+" 1. You may copy and distribute verbatim copies of the Program's\r\n"
+"source code as you receive it, in any medium, provided that you\r\n"
+"conspicuously and appropriately publish on each copy an appropriate\r\n"
+"copyright notice and disclaimer of warranty; keep intact all the\r\n"
+"notices that refer to this License and to the absence of any warranty;\r\n"
+"and give any other recipients of the Program a copy of this License\r\n"
+"along with the Program.\r\n"
+"\r\n"
+"You may charge a fee for the physical act of transferring a copy, and\r\n"
+"you may at your option offer warranty protection in exchange for a fee.\r\n"
+"\r\n"
+" 2. You may modify your copy or copies of the Program or any portion\r\n"
+"of it, thus forming a work based on the Program, and copy and\r\n"
+"distribute such modifications or work under the terms of Section 1\r\n"
+"above, provided that you also meet all of these conditions:\r\n"
+"\r\n"
+" a) You must cause the modified files to carry prominent notices\r\n"
+" stating that you changed the files and the date of any change.\r\n"
+"\r\n"
+" b) You must cause any work that you distribute or publish, that in\r\n"
+" whole or in part contains or is derived from the Program or any\r\n"
+" part thereof, to be licensed as a whole at no charge to all third\r\n"
+" parties under the terms of this License.\r\n"
+"\r\n"
+" c) If the modified program normally reads commands interactively\r\n"
+" when run, you must cause it, when started running for such\r\n"
+" interactive use in the most ordinary way, to print or display an\r\n"
+" announcement including an appropriate copyright notice and a\r\n"
+" notice that there is no warranty (or else, saying that you provide\r\n"
+" a warranty) and that users may redistribute the program under\r\n"
+" these conditions, and telling the user how to view a copy of this\r\n"
+" License. (Exception: if the Program itself is interactive but\r\n"
+" does not normally print such an announcement, your work based on\r\n"
+" the Program is not required to print an announcement.)\r\n"
+"\r\n"
+"These requirements apply to the modified work as a whole. If\r\n"
+"identifiable sections of that work are not derived from the Program,\r\n"
+"and can be reasonably considered independent and separate works in\r\n"
+"themselves, then this License, and its terms, do not apply to those\r\n"
+"sections when you distribute them as separate works. But when you\r\n"
+"distribute the same sections as part of a whole which is a work based\r\n"
+"on the Program, the distribution of the whole must be on the terms of\r\n"
+"this License, whose permissions for other licensees extend to the\r\n"
+"entire whole, and thus to each and every part regardless of who wrote it.\r\n"
+"\r\n"
+"Thus, it is not the intent of this section to claim rights or contest\r\n"
+"your rights to work written entirely by you; rather, the intent is to\r\n"
+"exercise the right to control the distribution of derivative or\r\n"
+"collective works based on the Program.\r\n"
+"\r\n"
+"In addition, mere aggregation of another work not based on the Program\r\n"
+"with the Program (or with a work based on the Program) on a volume of\r\n"
+"a storage or distribution medium does not bring the other work under\r\n"
+"the scope of this License.\r\n"
+"\r\n"
+" 3. You may copy and distribute the Program (or a work based on it,\r\n"
+"under Section 2) in object code or executable form under the terms of\r\n"
+"Sections 1 and 2 above provided that you also do one of the following:\r\n"
+"\r\n"
+" a) Accompany it with the complete corresponding machine-readable\r\n"
+" source code, which must be distributed under the terms of Sections\r\n"
+" 1 and 2 above on a medium customarily used for software interchange; or,\r\n"
+"\r\n"
+" b) Accompany it with a written offer, valid for at least three\r\n"
+" years, to give any third party, for a charge no more than your\r\n"
+" cost of physically performing source distribution, a complete\r\n"
+" machine-readable copy of the corresponding source code, to be\r\n"
+" distributed under the terms of Sections 1 and 2 above on a medium\r\n"
+" customarily used for software interchange; or,\r\n"
+"\r\n"
+" c) Accompany it with the information you received as to the offer\r\n"
+" to distribute corresponding source code. (This alternative is\r\n"
+" allowed only for noncommercial distribution and only if you\r\n"
+" received the program in object code or executable form with such\r\n"
+" an offer, in accord with Subsection b above.)\r\n"
+"\r\n"
+"The source code for a work means the preferred form of the work for\r\n"
+"making modifications to it. For an executable work, complete source\r\n"
+"code means all the source code for all modules it contains, plus any\r\n"
+"associated interface definition files, plus the scripts used to\r\n"
+"control compilation and installation of the executable. However, as a\r\n"
+"special exception, the source code distributed need not include\r\n"
+"anything that is normally distributed (in either source or binary\r\n"
+"form) with the major components (compiler, kernel, and so on) of the\r\n"
+"operating system on which the executable runs, unless that component\r\n"
+"itself accompanies the executable.\r\n"
+"\r\n"
+"If distribution of executable or object code is made by offering\r\n"
+"access to copy from a designated place, then offering equivalent\r\n"
+"access to copy the source code from the same place counts as\r\n"
+"distribution of the source code, even though third parties are not\r\n"
+"compelled to copy the source along with the object code.\r\n"
+"\r\n"
+" 4. You may not copy, modify, sublicense, or distribute the Program\r\n"
+"except as expressly provided under this License. Any attempt\r\n"
+"otherwise to copy, modify, sublicense or distribute the Program is\r\n"
+"void, and will automatically terminate your rights under this License.\r\n"
+"However, parties who have received copies, or rights, from you under\r\n"
+"this License will not have their licenses terminated so long as such\r\n"
+"parties remain in full compliance.\r\n"
+"\r\n"
+" 5. You are not required to accept this License, since you have not\r\n"
+"signed it. However, nothing else grants you permission to modify or\r\n"
+"distribute the Program or its derivative works. These actions are\r\n"
+"prohibited by law if you do not accept this License. Therefore, by\r\n"
+"modifying or distributing the Program (or any work based on the\r\n"
+"Program), you indicate your acceptance of this License to do so, and\r\n"
+"all its terms and conditions for copying, distributing or modifying\r\n"
+"the Program or works based on it.\r\n"
+"\r\n"
+" 6. Each time you redistribute the Program (or any work based on the\r\n"
+"Program), the recipient automatically receives a license from the\r\n"
+"original licensor to copy, distribute or modify the Program subject to\r\n"
+"these terms and conditions. You may not impose any further\r\n"
+"restrictions on the recipients' exercise of the rights granted herein.\r\n"
+"You are not responsible for enforcing compliance by third parties to\r\n"
+"this License.\r\n"
+"\r\n"
+" 7. If, as a consequence of a court judgment or allegation of patent\r\n"
+"infringement or for any other reason (not limited to patent issues),\r\n"
+"conditions are imposed on you (whether by court order, agreement or\r\n"
+"otherwise) that contradict the conditions of this License, they do not\r\n"
+"excuse you from the conditions of this License. If you cannot\r\n"
+"distribute so as to satisfy simultaneously your obligations under this\r\n"
+"License and any other pertinent obligations, then as a consequence you\r\n"
+"may not distribute the Program at all. For example, if a patent\r\n"
+"license would not permit royalty-free redistribution of the Program by\r\n"
+"all those who receive copies directly or indirectly through you, then\r\n"
+"the only way you could satisfy both it and this License would be to\r\n"
+"refrain entirely from distribution of the Program.\r\n"
+"\r\n"
+"If any portion of this section is held invalid or unenforceable under\r\n"
+"any particular circumstance, the balance of the section is intended to\r\n"
+"apply and the section as a whole is intended to apply in other\r\n"
+"circumstances.\r\n"
+"\r\n"
+"It is not the purpose of this section to induce you to infringe any\r\n"
+"patents or other property right claims or to contest validity of any\r\n"
+"such claims; this section has the sole purpose of protecting the\r\n"
+"integrity of the free software distribution system, which is\r\n"
+"implemented by public license practices. Many people have made\r\n"
+"generous contributions to the wide range of software distributed\r\n"
+"through that system in reliance on consistent application of that\r\n"
+"system; it is up to the author/donor to decide if he or she is willing\r\n"
+"to distribute software through any other system and a licensee cannot\r\n"
+"impose that choice.\r\n"
+"\r\n"
+"This section is intended to make thoroughly clear what is believed to\r\n"
+"be a consequence of the rest of this License.\r\n"
+"\r\n"
+" 8. If the distribution and/or use of the Program is restricted in\r\n"
+"certain countries either by patents or by copyrighted interfaces, the\r\n"
+"original copyright holder who places the Program under this License\r\n"
+"may add an explicit geographical distribution limitation excluding\r\n"
+"those countries, so that distribution is permitted only in or among\r\n"
+"countries not thus excluded. In such case, this License incorporates\r\n"
+"the limitation as if written in the body of this License.\r\n"
+"\r\n"
+" 9. The Free Software Foundation may publish revised and/or new versions\r\n"
+"of the General Public License from time to time. Such new versions will\r\n"
+"be similar in spirit to the present version, but may differ in detail to\r\n"
+"address new problems or concerns.\r\n"
+"\r\n"
+"Each version is given a distinguishing version number. If the Program\r\n"
+"specifies a version number of this License which applies to it and \"any\r\n"
+"later version\", you have the option of following the terms and conditions\r\n"
+"either of that version or of any later version published by the Free\r\n"
+"Software Foundation. If the Program does not specify a version number of\r\n"
+"this License, you may choose any version ever published by the Free Software\r\n"
+"Foundation.\r\n"
+"\r\n"
+" 10. If you wish to incorporate parts of the Program into other free\r\n"
+"programs whose distribution conditions are different, write to the author\r\n"
+"to ask for permission. For software which is copyrighted by the Free\r\n"
+"Software Foundation, write to the Free Software Foundation; we sometimes\r\n"
+"make exceptions for this. Our decision will be guided by the two goals\r\n"
+"of preserving the free status of all derivatives of our free software and\r\n"
+"of promoting the sharing and reuse of software generally.\r\n"
+"\r\n"
+" NO WARRANTY\r\n"
+"\r\n"
+" 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY\r\n"
+"FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN\r\n"
+"OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES\r\n"
+"PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED\r\n"
+"OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\r\n"
+"MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS\r\n"
+"TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE\r\n"
+"PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,\r\n"
+"REPAIR OR CORRECTION.\r\n"
+"\r\n"
+" 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\r\n"
+"WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR\r\n"
+"REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,\r\n"
+"INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING\r\n"
+"OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED\r\n"
+"TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY\r\n"
+"YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER\r\n"
+"PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE\r\n"
+"POSSIBILITY OF SUCH DAMAGES.\r\n"
+"\r\n"
+" END OF TERMS AND CONDITIONS\r\n"
+"\r\n"
+" How to Apply These Terms to Your New Programs\r\n"
+"\r\n"
+" If you develop a new program, and you want it to be of the greatest\r\n"
+"possible use to the public, the best way to achieve this is to make it\r\n"
+"free software which everyone can redistribute and change under these terms.\r\n"
+"\r\n"
+" To do so, attach the following notices to the program. It is safest\r\n"
+"to attach them to the start of each source file to most effectively\r\n"
+"convey the exclusion of warranty; and each file should have at least\r\n"
+"the \"copyright\" line and a pointer to where the full notice is found.\r\n"
+"\r\n"
+" \r\n"
+" Copyright (C) \r\n"
+"\r\n"
+" This program is free software; you can redistribute it and/or modify\r\n"
+" it under the terms of the GNU General Public License as published by\r\n"
+" the Free Software Foundation; either version 2 of the License, or\r\n"
+" (at your option) any later version.\r\n"
+"\r\n"
+" This program is distributed in the hope that it will be useful,\r\n"
+" but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n"
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r\n"
+" GNU General Public License for more details.\r\n"
+"\r\n"
+" You should have received a copy of the GNU General Public License\r\n"
+" along with this program; if not, write to the Free Software\r\n"
+" Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\r\n"
+"\r\n"
+"\r\n"
+"Also add information on how to contact you by electronic and paper mail.\r\n"
+"\r\n"
+"If the program is interactive, make it output a short notice like this\r\n"
+"when it starts in an interactive mode:\r\n"
+"\r\n"
+" Gnomovision version 69, Copyright (C) year name of author\r\n"
+" Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\r\n"
+" This is free software, and you are welcome to redistribute it\r\n"
+" under certain conditions; type `show c' for details.\r\n"
+"\r\n"
+"The hypothetical commands `show w' and `show c' should show the appropriate\r\n"
+"parts of the General Public License. Of course, the commands you use may\r\n"
+"be called something other than `show w' and `show c'; they could even be\r\n"
+"mouse-clicks or menu items--whatever suits your program.\r\n"
+"\r\n"
+"You should also get your employer (if you work as a programmer) or your\r\n"
+"school, if any, to sign a \"copyright disclaimer\" for the program, if\r\n"
+"necessary. Here is a sample; alter the names:\r\n"
+"\r\n"
+" Yoyodyne, Inc., hereby disclaims all copyright interest in the program\r\n"
+" `Gnomovision' (which makes passes at compilers) written by James Hacker.\r\n"
+"\r\n"
+" , 1 April 1989\r\n"
+" Ty Coon, President of Vice\r\n"
+"\r\n"
+"This General Public License does not permit incorporating your program into\r\n"
+"proprietary programs. If your program is a subroutine library, you may\r\n"
+"consider it more useful to permit linking proprietary applications with the\r\n"
+"library. If this is what you want to do, use the GNU Library General\r\n"
+"Public License instead of this License.\r\n";
diff -Nru swftools-0.9.2+ds1/installer/installer.c swftools-0.9.1/installer/installer.c
--- swftools-0.9.2+ds1/installer/installer.c 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/installer/installer.c 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,1009 @@
+/* installer.c
+
+ Part of the rfx installer (Main program).
+
+ Copyright (c) 2004-2008 Matthias Kramm
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "installer.h"
+#ifndef DEINSTALL
+#include "archive.h"
+#endif
+#include "utils.h"
+
+static int config_forAllUsers = 0;
+static int config_createLinks = 0;
+static int config_createStartmenu = 1;
+static int config_createDesktop = 1;
+static int config_deleteextra = 1;
+
+static char path_startmenu[MAX_PATH] = "\0";
+static char path_desktop[MAX_PATH] = "\0";
+static char path_programfiles[MAX_PATH] = "\0";
+
+static char pathBuf[MAX_PATH];
+static int do_abort = 0;
+
+static char* pdf2swf_dir;
+static char* pdf2swf_path;
+
+static char registry_path[1024];
+
+static char elevated = 0;
+
+static char*install_path = "c:\\swftools\\";
+#define SOFTWARE_DOMAIN "quiss.org"
+#define SOFTWARE_NAME "SWFTools"
+#define INSTALLER_NAME "SWFTools Installer"
+
+static HBITMAP logo = 0;
+
+static HINSTANCE me;
+
+#define USER_SETMESSAGE 0x7f01
+
+#ifndef DEINSTALL
+extern char*crndata;
+extern int crndata_len;
+extern int crn_decompressed_size;
+extern char*license_text;
+
+#include "background.c"
+#endif
+
+typedef struct _filelist
+{
+ const char*filename;
+ struct _filelist*next;
+ char type;
+} filelist_t;
+
+static filelist_t* registerFile(filelist_t*next, const char*filename, char type)
+{
+ filelist_t*file = malloc(sizeof(filelist_t));
+ file->filename = strdup(filename);
+ file->type = type;
+ file->next = next;
+ return file;
+}
+
+static filelist_t* readFileList(char*filename)
+{
+ FILE*fi = fopen(filename, "rb");
+ if(!fi) {
+ return 0;
+ }
+ fseek(fi, 0, SEEK_END);
+ int len = ftell(fi);
+ fseek(fi, 0, SEEK_SET);
+ char*data = malloc(len+1);
+ fread(data, len, 1, fi);
+ fclose(fi);
+ int t=0;
+ char*line = data;
+ filelist_t*list = 0,*lpos=0;;
+ while(ttype=line[0];
+ f->filename=strdup(line+2);
+ f->next = 0;
+ if(!list) {
+ list = lpos = f;
+ } else {
+ lpos->next = f;
+ lpos = f;
+ }
+ } else {
+ // skip line- this usually only happens if somebody tampered
+ // with the file
+ }
+ while(ttype, file->filename);
+ file = file->next;
+ }
+ fclose(fi);
+}
+
+static filelist_t*installedFiles = 0;
+
+static void addFile(const char*filename)
+{
+ installedFiles = registerFile(installedFiles, filename, 'F');
+}
+static void addDir(const char*filename)
+{
+ installedFiles = registerFile(installedFiles, filename, 'D');
+}
+
+static void handleTemplateFile(const char*filename)
+{
+ FILE*fi = fopen(filename, "rb");
+ fseek(fi, 0, SEEK_END);
+ int len = ftell(fi);
+ fseek(fi, 0, SEEK_SET);
+ char*file = malloc(len+1);
+ fread(file, len, 1, fi);
+ fclose(fi);
+ int l = strlen(install_path);
+ fi = fopen(filename, "wb");
+ char*pos = file;
+ char*lastpos = file;
+ while(1) {
+ pos = strstr(pos, "%%PATH%%");
+ if(!pos) {
+ pos = &file[len];
+ break;
+ }
+ if(pos!=lastpos)
+ fwrite(lastpos, pos-lastpos, 1, fi);
+ fwrite(install_path, l, 1, fi);
+ pos+=8; // length of "%%PATH%%"
+ lastpos = pos;
+ }
+ fwrite(lastpos, pos-lastpos, 1, fi);
+ fclose(fi);
+ free(file);
+}
+
+static int setRegistryEntry(char*key,char*value)
+{
+ HKEY hkey1;
+ HKEY hkey2;
+ int ret1 = -1, ret2= -1;
+ ret1 = RegCreateKey(HKEY_CURRENT_USER, key, &hkey1);
+ if(config_forAllUsers) {
+ ret2 = RegCreateKey(HKEY_LOCAL_MACHINE, key, &hkey2);
+ }
+
+ if(ret1 && ret2) {
+ fprintf(stderr, "registry: CreateKey %s failed\n", key);
+ return 0;
+ }
+ if(ret1) {
+ installedFiles = registerFile(installedFiles, key, 'k');
+ }
+ if(ret2) {
+ installedFiles = registerFile(installedFiles, key, 'K');
+ }
+
+ if(!ret1)
+ ret1 = RegSetValue(hkey1, NULL, REG_SZ, value, strlen(value)+1);
+ if(!ret2)
+ ret2 = RegSetValue(hkey2, NULL, REG_SZ, value, strlen(value)+1);
+ if(ret1 && ret2) {
+ fprintf(stderr, "registry: SetValue %s failed\n", key);
+ return 0;
+ }
+ return 1;
+}
+
+
+static char* getRegistryEntry(char*path)
+{
+ int res = 0;
+ HKEY key;
+ long rc;
+ long size = 0;
+ DWORD type;
+ char*buf;
+ rc = RegOpenKeyEx(HKEY_LOCAL_MACHINE, path, 0, KEY_ALL_ACCESS/* KEY_READ*/, &key);
+ if (rc != ERROR_SUCCESS) {
+ fprintf(stderr, "RegOpenKeyEx failed\n");
+ return 0;
+ }
+ rc = RegQueryValueEx(key, NULL, 0, 0, 0, (LPDWORD)&size) ;
+ if(rc != ERROR_SUCCESS) {
+ fprintf(stderr, "RegQueryValueEx(1) failed: %d\n", rc);
+ return 0;
+ }
+ buf = (char*)malloc(size+1);
+ rc = RegQueryValueEx(key, NULL, 0, &type, (BYTE*)buf, (LPDWORD)&size);
+ if(rc != ERROR_SUCCESS) {
+ fprintf(stderr, "RegQueryValueEx(2) failed: %d\n", rc);
+ return 0;
+ }
+ if(type == REG_SZ || type == REG_EXPAND_SZ) {
+ while(size && buf[size-1] == '\0')
+ --size;
+ buf[size] = 0;
+ /* TODO: convert */
+ return buf;
+ } else if(type == REG_BINARY) {
+ return buf;
+ }
+}
+
+static int has_full_access = 0;
+static char hasFullAccess()
+{
+ /* find out whether we can write keys in HKEY_LOCAL_MACHINE */
+ HKEY hKey;
+ int ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall", 0,
+ KEY_CREATE_SUB_KEY, &hKey);
+ if(!ret) {
+ RegCloseKey(hKey);
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+void processMessages()
+{
+ MSG msg;
+ while(PeekMessage(&msg,NULL,0,0,0))
+ {
+ GetMessage(&msg, NULL, 0, 0);
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+}
+
+int addRegistryEntries(char*install_dir)
+{
+ int ret;
+ ret = setRegistryEntry(registry_path, install_dir);
+ if(!ret) return 0;
+ return 1;
+}
+
+int CreateShortcut(char*path, char*description, char*filename, char*arguments, int iconindex, char*iconpath, char*workdir)
+{
+ printf("Creating %s -> %s\n", filename, path);
+ WCHAR wszFilename[MAX_PATH];
+ IShellLink *ps1 = NULL;
+ IPersistFile *pPf = NULL;
+ HRESULT hr;
+ hr = CoCreateInstance(&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, &IID_IShellLink, (void*)&ps1);
+ if(FAILED(hr)) return 0;
+ hr = ps1->lpVtbl->QueryInterface(ps1, &IID_IPersistFile, (void **)&pPf);
+ if(FAILED(hr)) return 0;
+ hr = ps1->lpVtbl->SetPath(ps1, path);
+ if(FAILED(hr)) return 0;
+ hr = ps1->lpVtbl->SetDescription(ps1, description);
+
+ if (arguments) {
+ hr = ps1->lpVtbl->SetArguments(ps1, arguments);
+ if(FAILED(hr)) return 0;
+ }
+ if (iconpath) {
+ hr = ps1->lpVtbl->SetIconLocation(ps1, iconpath, iconindex);
+ if (FAILED(hr)) return 0;
+ }
+ if (workdir) {
+ hr = ps1->lpVtbl->SetWorkingDirectory(ps1, workdir);
+ if (FAILED(hr)) return 0;
+ }
+ MultiByteToWideChar(CP_ACP, 0, filename, -1, wszFilename, MAX_PATH);
+ hr = pPf->lpVtbl->Save(pPf, wszFilename, TRUE);
+ if(FAILED(hr)) {
+ return 0;
+ }
+ pPf->lpVtbl->Release(pPf);
+ ps1->lpVtbl->Release(ps1);
+ addFile(filename);
+ return 1;
+}
+
+static int CreateURL(const char*url, const char*path)
+{
+ FILE*fi = fopen(path, "wb");
+ if(!fi)
+ return 0;
+ fprintf(fi, "[InternetShortcut]\r\n");
+ fprintf(fi, "URL=http://localhost:8081/\r\n");
+ fclose(fi);
+ addFile(path);
+ return 1;
+}
+
+
+BOOL CALLBACK PropertySheetFuncCommon(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam, int buttons)
+{
+ LPNMHDR lpnm;
+
+ HWND dialog = GetParent(hwnd);
+
+ if(message == WM_INITDIALOG) {
+ if(logo)
+ SendDlgItemMessage(hwnd, IDC_BITMAP, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)logo);
+
+ RECT rc;
+ GetWindowRect(dialog, &rc);
+ int width = rc.right - rc.left;
+ int height = rc.bottom - rc.top;
+ MoveWindow(dialog, (GetSystemMetrics(SM_CXSCREEN) - width)/2, (GetSystemMetrics(SM_CYSCREEN) - height)/2, width, height, FALSE);
+ return FALSE;
+ }
+
+ if(message == WM_NOTIFY && (((LPNMHDR)lParam)->code == PSN_SETACTIVE)) {
+ PropSheet_SetWizButtons(dialog, buttons);
+ return FALSE;
+ }
+ return FALSE;
+}
+
+#ifndef DEINSTALL
+BOOL CALLBACK PropertySheetFunc1(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
+ if(message == WM_INITDIALOG) {
+ SetDlgItemText(hwnd, IDC_LICENSE, license_text);
+ }
+ return PropertySheetFuncCommon(hwnd, message, wParam, lParam, PSWIZB_NEXT);
+}
+BOOL CALLBACK PropertySheetFunc2(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
+ if(message == WM_INITDIALOG) {
+ SetDlgItemText(hwnd, IDC_INSTALL_PATH, install_path);
+
+ SendDlgItemMessage(hwnd, IDC_ALLUSERS, BM_SETCHECK, config_forAllUsers, 0);
+ SendDlgItemMessage(hwnd, IDC_CURRENTUSER, BM_SETCHECK, config_forAllUsers^1, 0);
+ }
+ if(message == WM_COMMAND) {
+ if((wParam&0xffff) == IDC_BROWSE) {
+ BROWSEINFOA browse;
+ memset(&browse, 0, sizeof(browse));
+ browse.ulFlags = BIF_EDITBOX | BIF_NEWDIALOGSTYLE | BIF_USENEWUI;// | BIF_RETURNONLYFSDIRS; //BIF_VALIDATE
+ browse.pszDisplayName = (CHAR*)malloc(MAX_PATH);
+ memset(browse.pszDisplayName, 0, MAX_PATH);
+ browse.lpszTitle = "Select installation directory";
+ browse.pidlRoot = SHBrowseForFolder(&browse);
+ if(browse.pszDisplayName) {
+ if(SHGetPathFromIDList(browse.pidlRoot, browse.pszDisplayName)) {
+ install_path = browse.pszDisplayName;
+ int l = strlen(install_path);
+ while(l && install_path[l-1]=='\\') {
+ install_path[--l]=0;
+ }
+ }
+ }
+ SendDlgItemMessage(hwnd, IDC_INSTALL_PATH, WM_SETTEXT, 0, (LPARAM)install_path);
+ return 0;
+
+ }
+ else if((wParam&0xffff) == IDC_ALLUSERS) {
+ config_forAllUsers = 1;
+ SendDlgItemMessage(hwnd, IDC_ALLUSERS, BM_SETCHECK, config_forAllUsers, 0);
+ SendDlgItemMessage(hwnd, IDC_CURRENTUSER, BM_SETCHECK, config_forAllUsers^1, 0);
+ }
+ else if((wParam&0xffff) == IDC_CURRENTUSER) {
+ config_forAllUsers = 0;
+ SendDlgItemMessage(hwnd, IDC_ALLUSERS, BM_SETCHECK, config_forAllUsers, 0);
+ SendDlgItemMessage(hwnd, IDC_CURRENTUSER, BM_SETCHECK, config_forAllUsers^1, 0);
+ }
+ else if((wParam&0xffff) == IDC_INSTALL_PATH) {
+ SendDlgItemMessage(hwnd, IDC_INSTALL_PATH, WM_GETTEXT, sizeof(pathBuf), (LPARAM)&(pathBuf[0]));
+ if(pathBuf[0]) {
+ install_path = pathBuf;
+ int l = strlen(install_path);
+ while(l && install_path[l-1]=='\\') {
+ install_path[--l]=0;
+ }
+ }
+ return 0;
+ }
+ }
+ if(message == WM_NOTIFY && (((LPNMHDR)lParam)->code == PSN_SETACTIVE)) {
+ if(!elevated && !has_full_access) {
+ OSVERSIONINFO winverinfo;
+ memset(&winverinfo, 0, sizeof(OSVERSIONINFO));
+ winverinfo.dwOSVersionInfoSize = sizeof(winverinfo);
+ if (GetVersionEx(&winverinfo) && winverinfo.dwMajorVersion >= 5) {
+ /* we're on Vista, were asked to install for all users, but don't have
+ priviledges to do so. Ask to spawn the process elevated. */
+ char exename[MAX_PATH];
+ GetModuleFileName(NULL, exename, sizeof(exename));
+ if((int)ShellExecute(0, "runas", exename, "elevated", NULL, SW_SHOWNORMAL)>32) {
+ /* that worked- the second process will do the work */
+ exit(0);
+ }
+ }
+ }
+ }
+ return PropertySheetFuncCommon(hwnd, message, wParam, lParam, PSWIZB_BACK|PSWIZB_NEXT);
+}
+HWND statuswnd;
+static int progress_pos = 0;
+
+void PropertyArchiveError(char*text)
+{
+ while(1) {
+ int ret = MessageBox(0, text, "Error", MB_RETRYCANCEL|MB_ICONERROR);
+ if(ret==IDRETRY) continue;
+ else break;
+ }
+}
+
+void PropertyArchive_NewFile(char*filename)
+{
+ addFile(filename);
+ processMessages();
+}
+void PropertyArchive_NewDirectory(char*filename)
+{
+ addDir(filename);
+ processMessages();
+}
+
+static int lastlen = 0;
+void PropertyArchiveStatus(int pos, int len)
+{
+ if(len!=lastlen) {
+ SendDlgItemMessage(statuswnd, IDC_PROGRESS, PBM_SETRANGE, 0, (LPARAM)MAKELONG(0,len));
+ lastlen = len;
+ }
+ SendDlgItemMessage(statuswnd, IDC_PROGRESS, PBM_SETPOS, pos, 0);
+ processMessages();
+ Sleep(30);
+}
+void PropertyArchiveMessage(char*text)
+{
+ if(text && text[0]=='[') {
+ return;
+ }
+ SetDlgItemText(statuswnd, IDC_INFO, strdup(text));
+ processMessages();
+}
+
+void print_space(char*dest, char*msg, ULONGLONG size)
+{
+ if(size < 1024)
+ sprintf(dest, "%s%d Bytes", msg, size);
+ else if(size < 1048576l)
+ sprintf(dest, "%s%.2f Kb", msg, size/1024.0);
+ else if(size < 1073741824l)
+ sprintf(dest, "%s%.2f Mb", msg, size/1048576.0);
+ else if(size < 1099511627776ll)
+ sprintf(dest, "%s%.2f Gb", msg, size/1073741824.0);
+ else
+ sprintf(dest, "%s%.2f Tb", msg, size/1125899906842624.0);
+}
+
+BOOL CALLBACK PropertySheetFunc3(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
+ HWND dialog = GetParent(hwnd);
+ if(message == WM_INITDIALOG) {
+ SetDlgItemText(hwnd, IDC_INFO, "Ready to install");
+
+ char buf[256];
+ print_space(buf, "Space required: ", crn_decompressed_size);
+ SetDlgItemText(hwnd, IDC_SPACE1, buf);
+ ULARGE_INTEGER available,total,totalfree;
+ available.QuadPart=0;
+ total.QuadPart=0;
+ totalfree.QuadPart=0;
+ if(GetDiskFreeSpaceEx(install_path, &available, &total, &totalfree)) {
+ print_space(buf, "Space available: ", available.QuadPart);
+ } else {
+ sprintf(buf, "Space available: [Error %d]", GetLastError());
+ if((GetLastError() == ERROR_FILE_NOT_FOUND || GetLastError() == ERROR_PATH_NOT_FOUND)
+ && install_path[0] && install_path[1]==':') {
+ /* installation directory does not yet exist */
+ char path[3]={'c',':',0};
+ path[0] = install_path[0];
+ if(GetDiskFreeSpaceEx(path, &available, &total, &totalfree)) {
+ print_space(buf, "Space available: ", available.QuadPart);
+ }
+ }
+ }
+ SetDlgItemText(hwnd, IDC_SPACE2, buf);
+ }
+ if(message == WM_NOTIFY && (((LPNMHDR)lParam)->code == PSN_WIZNEXT)) {
+ SetDlgItemText(hwnd, IDC_SPACE1, "");
+ SetDlgItemText(hwnd, IDC_SPACE2, "");
+ PropSheet_SetWizButtons(dialog, 0);
+ SendMessage(dialog, PSM_CANCELTOCLOSE, 0, 0); //makes wine display a warning
+ SetDlgItemText(hwnd, IDC_TITLE, "Installing...");
+ statuswnd = hwnd;
+ status_t status;
+ status.status = PropertyArchiveStatus;
+ status.message = PropertyArchiveMessage;
+ status.error = PropertyArchiveError;
+ status.new_file = PropertyArchive_NewFile;
+ status.new_directory = PropertyArchive_NewDirectory;
+ int success = unpack_archive(crndata, crndata_len, install_path, &status);
+ memset(&status, 0, sizeof(status_t));
+ if(!success) {
+ MessageBox(0, "Couldn't extract all installation files", INSTALLER_NAME, MB_OK|MB_ICONERROR);
+ do_abort=1;
+ exit(1);
+ }
+ return 0;
+ }
+ return PropertySheetFuncCommon(hwnd, message, wParam, lParam, PSWIZB_BACK|PSWIZB_NEXT);
+}
+
+static HRESULT (WINAPI *f_SHGetSpecialFolderPath)(HWND hwnd, LPTSTR lpszPath, int nFolder, BOOL fCreate);
+
+BOOL CALLBACK PropertySheetFunc4(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
+ if(message == WM_INITDIALOG) {
+ pdf2swf_dir = install_path; //concatPaths(install_path, "gpdf2swf");
+ pdf2swf_path = concatPaths(pdf2swf_dir, "gpdf2swf.exe");
+ FILE*fi = fopen(pdf2swf_path, "rb");
+ if(fi) {
+ printf("a GUI program exists, creating desktop/startmenu links\n");
+ config_createLinks = 1;
+ fclose(fi);
+ } else {
+ config_createLinks = 0;
+ config_createStartmenu = 0;
+ config_createDesktop = 0;
+ }
+ if(!config_createLinks) {
+ SendDlgItemMessage(hwnd, IDC_STARTMENU, BN_DISABLE, 0, 0);
+ SendDlgItemMessage(hwnd, IDC_DESKTOP, BN_DISABLE, 0, 0);
+ }
+
+ SendDlgItemMessage(hwnd, IDC_STARTMENU, BM_SETCHECK, config_createStartmenu, 0);
+ SendDlgItemMessage(hwnd, IDC_DESKTOP, BM_SETCHECK, config_createDesktop, 0);
+ }
+ if(message == WM_COMMAND) {
+ if((wParam&0xffff) == IDC_STARTMENU) {
+ config_createStartmenu = SendDlgItemMessage(hwnd, IDC_STARTMENU, BM_GETCHECK, 0, 0);
+ if(config_createLinks) {
+ config_createStartmenu^=1;
+ }
+ SendDlgItemMessage(hwnd, IDC_STARTMENU, BM_SETCHECK, config_createStartmenu, 0);
+ return 0;
+ }
+ if((wParam&0xffff) == IDC_DESKTOP) {
+ config_createDesktop = SendDlgItemMessage(hwnd, IDC_DESKTOP, BM_GETCHECK, 0, 0);
+ if(config_createLinks) {
+ config_createDesktop^=1;
+ }
+ SendDlgItemMessage(hwnd, IDC_DESKTOP, BM_SETCHECK, config_createDesktop, 0);
+ return 0;
+ }
+ }
+
+ if(message == WM_NOTIFY && (((LPNMHDR)lParam)->code == PSN_WIZFINISH)) {
+ if(!addRegistryEntries(install_path)) {
+ MessageBox(0, "Couldn't create Registry Entries", INSTALLER_NAME, MB_OK|MB_ICONERROR);
+ return 1;
+ }
+
+ char mypath[MAX_PATH];
+ path_startmenu[0] = 0;
+ path_desktop[0] = 0;
+ if(config_forAllUsers) {
+ f_SHGetSpecialFolderPath(NULL, path_desktop, CSIDL_COMMON_DESKTOPDIRECTORY, 0);
+ f_SHGetSpecialFolderPath(NULL, path_startmenu, CSIDL_COMMON_PROGRAMS, 0);
+ }
+ /* get local program/desktop directory- this is both for forAllUsers=0 as well
+ as a fallback if the above didn't return any paths */
+ if(!path_startmenu[0]) {
+ f_SHGetSpecialFolderPath(NULL, path_startmenu, CSIDL_PROGRAMS, 0);
+ }
+ if(!path_desktop[0]) {
+ f_SHGetSpecialFolderPath(NULL, path_desktop, CSIDL_DESKTOPDIRECTORY, 0);
+ }
+
+ char*uninstall_path = concatPaths(install_path, "uninstall.exe");
+
+ if(config_createLinks) {
+ if(config_createDesktop && path_desktop[0]) {
+ char* linkName = concatPaths(path_desktop, "pdf2swf.lnk");
+ printf("Creating desktop link %s -> %s\n", linkName, pdf2swf_path);
+ if(!CreateShortcut(pdf2swf_path, "pdf2swf", linkName, 0, 0, 0, pdf2swf_dir)) {
+ MessageBox(0, "Couldn't create desktop shortcut", INSTALLER_NAME, MB_OK);
+ return 1;
+ }
+ }
+ if(config_createStartmenu && path_startmenu[0]) {
+ char* group = concatPaths(path_startmenu, "pdf2swf");
+ CreateDirectory(group, 0);
+ addDir(group);
+ char* linkName = concatPaths(group, "pdf2swf.lnk");
+ if(!CreateShortcut(pdf2swf_path, "pdf2swf", concatPaths(group, "pdf2swf.lnk"), 0, 0, 0, pdf2swf_dir) ||
+ !CreateShortcut(uninstall_path, "uninstall", concatPaths(group, "uninstall.lnk"), 0, 0, 0, install_path)) {
+ MessageBox(0, "Couldn't create start menu entry", INSTALLER_NAME, MB_OK);
+ return 1;
+ }
+ }
+ } else {
+ printf("not creating desktop/startmenu links\n");
+ }
+
+ char*uninstall_ini = concatPaths(install_path, "uninstall.ini");
+ addFile(uninstall_ini);
+ writeFileList(installedFiles, uninstall_ini);
+ }
+ return PropertySheetFuncCommon(hwnd, message, wParam, lParam, PSWIZB_FINISH);
+}
+#endif
+
+#ifdef DEINSTALL
+
+void findfiles(char*path, int*pos, char*data, int len, char del)
+{
+ WIN32_FIND_DATA findFileData;
+ HANDLE hFind = FindFirstFile(concatPaths(path, "*"), &findFileData);
+ if(hFind == INVALID_HANDLE_VALUE)
+ return;
+ do {
+ if(findFileData.cFileName[0] == '.' &&
+ (findFileData.cFileName[0] == '.' || findFileData.cFileName == '\0'))
+ continue;
+ char*f = concatPaths(path, findFileData.cFileName);
+ if(findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
+ findfiles(f, pos, data, len, del);
+ /* always try to remove directories- if they are empty, this
+ will work, and they won't prevent superdirectory deletion later */
+ RemoveDirectory(f);
+ } else {
+ int l = strlen(f);
+
+ /* don't list the uninstaller as file- it's going to be removed *after*
+ everything else is done */
+ char*uninstaller="uninstall.exe";
+ int ll = strlen(uninstaller);
+ if(l>=ll) {
+ if(!strcasecmp(&f[l-ll],uninstaller)) {
+ continue;
+ }
+ }
+
+ if(data) {
+ if(*pos+l <= len) {
+ memcpy(&data[*pos], f, l);(*pos)+=l;
+ data[(*pos)++] = '\r';
+ data[(*pos)++] = '\n';
+ data[(*pos)] = 0;
+ }
+ } else {
+ (*pos) += l+2;
+ }
+ if(del) {
+ DeleteFile(f);
+ }
+ }
+ } while(FindNextFile(hFind, &findFileData));
+ FindClose(hFind);
+}
+
+static char*extrafiles = 0;
+
+BOOL CALLBACK PropertySheetFunc5(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
+ HWND dialog = GetParent(hwnd);
+ if(message == WM_INITDIALOG) {
+ SetDlgItemText(hwnd, IDC_INFO, "Ready to uninstall");
+ }
+ if(message == WM_NOTIFY && (((LPNMHDR)lParam)->code == PSN_WIZNEXT)) {
+
+ filelist_t* list = readFileList("uninstall.ini");
+ if(!list) {
+ list = readFileList(concatPaths(install_path, "uninstall.ini"));
+ if(!list) {
+ //Don't abort. If there's still something there, it'll be catched by the "extra files"
+ //functionality later
+ //MessageBox(0, "Couldn't determine installed files list- did you run uninstall twice?", INSTALLER_NAME, MB_OK);
+ //exit(-1);
+ }
+ }
+ filelist_t* l = list;
+ int num = 0;
+ while(l) {num++;l=l->next;}
+
+ PropSheet_SetWizButtons(dialog, 0);
+ SendMessage(dialog, PSM_CANCELTOCLOSE, 0, 0);
+ SetDlgItemText(hwnd, IDC_TITLE, "Uninstalling files...");
+ SendDlgItemMessage(hwnd, IDC_PROGRESS, PBM_SETRANGE, 0, (LPARAM)MAKELONG(0,num));
+ num = 0;
+ l = list;
+ while(l) {
+ SendDlgItemMessage(hwnd, IDC_PROGRESS, PBM_SETPOS, num, 0);
+ if(l->type=='F')
+ DeleteFile(l->filename);
+ else if(l->type=='D')
+ RemoveDirectory(l->filename);
+ else if(l->type=='I')
+ /* skip- we will remove ourselves later */;
+ num++;l = l->next;
+ }
+
+ int len = 0;
+ findfiles(install_path, &len, 0, 0, 0);
+ if(len) {
+ extrafiles = malloc(len);
+ int pos = 0;
+ findfiles(install_path, &pos, extrafiles, len, 0);
+ } else {
+ PropSheet_RemovePage(dialog, 1, 0);
+ }
+ return 0;
+ }
+ return PropertySheetFuncCommon(hwnd, message, wParam, lParam, PSWIZB_BACK|PSWIZB_NEXT);
+}
+
+BOOL CALLBACK PropertySheetFunc6(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
+ if(message == WM_INITDIALOG) {
+ SendDlgItemMessage(hwnd, IDC_DELETEEXTRA, BM_SETCHECK, config_deleteextra, 0);
+ if(extrafiles) {
+ SetDlgItemText(hwnd, IDC_FILELIST, extrafiles);
+ }
+ }
+ if(message == WM_COMMAND) {
+ if((wParam&0xffff) == IDC_DELETEEXTRA) {
+ config_deleteextra = SendDlgItemMessage(hwnd, IDC_DELETEEXTRA, BM_GETCHECK, 0, 0);
+ config_deleteextra ^=1;
+ SendDlgItemMessage(hwnd, IDC_DELETEEXTRA, BM_SETCHECK, config_deleteextra, 0);
+ return 0;
+ }
+ }
+ if(message == WM_NOTIFY && (((LPNMHDR)lParam)->code == PSN_WIZNEXT)) {
+ if(config_deleteextra) {
+ int pos = 0;
+ findfiles(install_path, &pos, 0, 0, 1);
+ }
+ }
+ return PropertySheetFuncCommon(hwnd, message, wParam, lParam, PSWIZB_NEXT);
+}
+
+BOOL CALLBACK PropertySheetFunc7(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
+ if(message == WM_INITDIALOG) {
+ // ...
+ }
+ return PropertySheetFuncCommon(hwnd, message, wParam, lParam, PSWIZB_FINISH);
+}
+#endif
+
+#ifndef PSP_HIDEHEADER
+#define PSP_HIDEHEADER 2048
+#endif
+
+typedef struct _wizardpage {
+ DLGPROC function;
+ int resource;
+} wizardpage_t;
+
+void runPropertySheet(HWND parent)
+{
+ PROPSHEETHEADER sheet;
+
+ wizardpage_t wpage[5] = {
+#ifndef DEINSTALL
+ {PropertySheetFunc1, IDD_LICENSE},
+ {PropertySheetFunc2, IDD_INSTALLDIR},
+ {PropertySheetFunc3, IDD_PROGRESS},
+ {PropertySheetFunc4, IDD_FINISH},
+#else
+ {PropertySheetFunc5, IDD_SURE},
+ {PropertySheetFunc6, IDD_EXTRAFILES},
+ {PropertySheetFunc7, IDD_DEINSTALLED},
+#endif
+ };
+
+ int num = sizeof(wpage)/sizeof(wpage[0]);
+
+#ifndef DEINSTALL
+ if(elevated) {
+ /* remove license.
+ TODO: remove installdir querying, too (pass installdir
+ to second process) */
+ int t;
+ for(t=1;t
+#include "installer.h"
+
+MYICON1 ICON "installer.ico"
+LOGO BITMAP "swftools.bmp"
+
+#define X 64
+
+IDD_LICENSE DIALOGEX 0, 0, 379-X, 178
+STYLE WS_CHILD | WS_DISABLED | WS_CAPTION
+CAPTION "Setup"
+FONT 8, "MS Sans Serif", 0, 0, 0x1
+BEGIN
+ LTEXT "This Installer will install swftools on your computer. Please read and sign the following license agreement.",
+ IDC_TITLE,125-X,10,247,20,NOT WS_GROUP
+ EDITTEXT IDC_LICENSE,125-X,31,247,131,ES_MULTILINE | ES_READONLY |
+ WS_VSCROLL | WS_HSCROLL | NOT WS_TABSTOP
+ CONTROL 110,IDC_BITMAP,"Static",SS_BITMAP | SS_CENTERIMAGE,6,8,
+ 104-X,163,WS_EX_CLIENTEDGE
+ LTEXT "Click next if you agree with this license.",IDC_STATIC,125-X,163,247,8
+END
+
+IDD_INSTALLDIR DIALOGEX 0, 0, 379-X, 178
+STYLE WS_CHILD | WS_DISABLED | WS_CAPTION
+CAPTION "Setup"
+FONT 8, "MS Sans Serif", 0, 0, 0x1
+BEGIN
+ LTEXT "Select installation directory:",IDC_TITLE,125-X,10,247,12,NOT WS_GROUP
+ PUSHBUTTON "Browse...",IDC_BROWSE,322-X,7,50,14,WS_VISIBLE
+ EDITTEXT IDC_INSTALL_PATH ,125-X,30,247,11,ES_AUTOHSCROLL
+
+ RADIOBUTTON "Install for all users", IDC_ALLUSERS, 125-X,60,247,8
+ RADIOBUTTON "Install only for the current user", IDC_CURRENTUSER, 125-X,80,247,8
+
+ CONTROL 110,IDC_BITMAP,"Static",SS_BITMAP | SS_CENTERIMAGE,6,8, 104-X,163,WS_EX_CLIENTEDGE
+END
+
+IDD_PROGRESS DIALOGEX 0, 0, 379-X, 178
+STYLE WS_CHILD | WS_DISABLED | WS_CAPTION
+CAPTION "Setup"
+FONT 8, "MS Sans Serif", 0, 0, 0x1
+BEGIN
+ LTEXT "Click ""Next"" to begin the install process. If you want to review or change any of your installation settings, click ""Back"". Click ""Cancel"" to exit the Installer.",
+ IDC_TITLE,125-X,10,246,31,NOT WS_GROUP
+ LTEXT "Required space: ",IDC_SPACE1,125-X,60,246,8,NOT WS_GROUP
+ LTEXT "Available space: ",IDC_SPACE2,125-X,80,246,8,NOT WS_GROUP
+ CONTROL "Progress1",IDC_PROGRESS,"msctls_progress32",WS_BORDER,
+ 125-X,157,246,14
+ CTEXT "Installation progress:",IDC_INFO,125-X,137,246,8
+ CONTROL 110,IDC_BITMAP,"Static",SS_BITMAP | SS_CENTERIMAGE,6,8,
+ 104-X,163,WS_EX_CLIENTEDGE
+END
+
+IDD_FINISH DIALOGEX 0, 0, 379-X, 178
+STYLE WS_CHILD | WS_DISABLED | WS_CAPTION
+CAPTION "Setup"
+FONT 8, "MS Sans Serif"
+BEGIN
+ LTEXT "Installation is finished.",
+ IDC_TITLE,125-X,10,247,31,NOT WS_GROUP
+ CHECKBOX "Create start menu entry", IDC_STARTMENU, 125-X,40,247,8
+ CHECKBOX "Create desktop shortcut", IDC_DESKTOP, 125-X,60,247,8
+ CONTROL 110,IDC_BITMAP,"Static",SS_BITMAP | SS_CENTERIMAGE,6,8,
+ 104-X,163,WS_EX_CLIENTEDGE
+END
+
+IDD_SURE DIALOGEX 0, 0, 379-X, 178
+STYLE WS_CHILD | WS_DISABLED | WS_CAPTION
+CAPTION "Setup"
+FONT 8, "MS Sans Serif", 0, 0, 0x1
+BEGIN
+ LTEXT "This program will uninstall the software from your computer. Click ""Next"" to remove all files and startmenu/desktop entries from this machine. Click ""Cancel"" to exit the Uninstaller.",
+ IDC_TITLE,125-X,10,246,31,NOT WS_GROUP
+ CONTROL "Progress1",IDC_PROGRESS,"msctls_progress32",WS_BORDER,
+ 125-X,157,246,14
+ CTEXT "Installation progress:",IDC_INFO,125-X,137,246,8
+ CONTROL 110,IDC_BITMAP,"Static",SS_BITMAP | SS_CENTERIMAGE,6,8,
+ 104-X,163,WS_EX_CLIENTEDGE
+END
+
+IDD_EXTRAFILES DIALOGEX 0, 0, 379-X, 178
+STYLE WS_CHILD | WS_DISABLED | WS_CAPTION
+CAPTION "Setup"
+FONT 8, "MS Sans Serif", 0, 0, 0x1
+BEGIN
+ LTEXT "The installation directory still contains files which were created after the initial installation. Please decide whether those files should be removed, too.",
+ IDC_TITLE,125-X,10,247,20,NOT WS_GROUP
+ EDITTEXT IDC_FILELIST,125-X,31,247,130,ES_MULTILINE | ES_READONLY |
+ WS_VSCROLL | WS_HSCROLL | NOT WS_TABSTOP
+ CHECKBOX "Delete the above files", IDC_DELETEEXTRA, 125-X,163,247,8
+ CONTROL 110,IDC_BITMAP,"Static",SS_BITMAP | SS_CENTERIMAGE,6,8,
+ 104-X,163,WS_EX_CLIENTEDGE
+END
+
+IDD_DEINSTALLED DIALOGEX 0, 0, 379-X, 178
+STYLE WS_CHILD | WS_DISABLED | WS_CAPTION
+CAPTION "Setup"
+FONT 8, "MS Sans Serif", 0, 0, 0x1
+BEGIN
+ LTEXT "Uninstallation is finished.",IDC_TITLE,125-X,10,246,31,NOT WS_GROUP
+ CONTROL 110,IDC_BITMAP,"Static",SS_BITMAP | SS_CENTERIMAGE,6,8, 104-X,163,WS_EX_CLIENTEDGE
+END
+
+
diff -Nru swftools-0.9.2+ds1/installer/lzma/LzmaDecode.c swftools-0.9.1/installer/lzma/LzmaDecode.c
--- swftools-0.9.2+ds1/installer/lzma/LzmaDecode.c 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/installer/lzma/LzmaDecode.c 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,593 @@
+/*
+ LzmaDecode.c
+ LZMA Decoder (optimized for Speed version)
+
+ LZMA SDK 4.40 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01)
+ http://www.7-zip.org/
+
+ LZMA SDK is licensed under two licenses:
+ 1) GNU Lesser General Public License (GNU LGPL)
+ 2) Common Public License (CPL)
+ It means that you can select one of these two licenses and
+ follow rules of that license.
+
+ SPECIAL EXCEPTION:
+ Igor Pavlov, as the author of this Code, expressly permits you to
+ statically or dynamically link your Code (or bind by name) to the
+ interfaces of this file without subjecting your linked Code to the
+ terms of the CPL or GNU LGPL. Any modifications or additions
+ to this file, however, are subject to the LGPL or CPL terms.
+*/
+
+#include
+#include
+
+#include "LzmaDecode.h"
+
+#define kNumTopBits 24
+#define kTopValue ((UInt32)1 << kNumTopBits)
+
+#define kNumBitModelTotalBits 11
+#define kBitModelTotal (1 << kNumBitModelTotalBits)
+#define kNumMoveBits 5
+
+#define RC_READ_BYTE (*Buffer++)
+
+#define RC_INIT2 Code = 0; Range = 0xFFFFFFFF; \
+ { int i; for(i = 0; i < 5; i++) { RC_TEST; Code = (Code << 8) | RC_READ_BYTE; }}
+
+#ifdef _LZMA_IN_CB
+
+#define RC_TEST { if (Buffer == BufferLim) \
+ { SizeT size; int result = InCallback->Read(InCallback, &Buffer, &size); if (result != LZMA_RESULT_OK) return result; \
+ BufferLim = Buffer + size; if (size == 0) return LZMA_RESULT_DATA_ERROR; }}
+
+#define RC_INIT Buffer = BufferLim = 0; RC_INIT2
+
+#else
+
+#define RC_TEST { if (Buffer == BufferLim) return LZMA_RESULT_DATA_ERROR; }
+
+#define RC_INIT(buffer, bufferSize) Buffer = buffer; BufferLim = buffer + bufferSize; RC_INIT2
+
+#endif
+
+#define RC_NORMALIZE if (Range < kTopValue) { RC_TEST; Range <<= 8; Code = (Code << 8) | RC_READ_BYTE; }
+
+#define IfBit0(p) RC_NORMALIZE; bound = (Range >> kNumBitModelTotalBits) * *(p); if (Code < bound)
+#define UpdateBit0(p) Range = bound; *(p) += (kBitModelTotal - *(p)) >> kNumMoveBits;
+#define UpdateBit1(p) Range -= bound; Code -= bound; *(p) -= (*(p)) >> kNumMoveBits;
+
+#define RC_GET_BIT2(p, mi, A0, A1) IfBit0(p) \
+ { UpdateBit0(p); mi <<= 1; A0; } else \
+ { UpdateBit1(p); mi = (mi + mi) + 1; A1; }
+
+#define RC_GET_BIT(p, mi) RC_GET_BIT2(p, mi, ; , ;)
+
+#define RangeDecoderBitTreeDecode(probs, numLevels, res) \
+ { int i = numLevels; res = 1; \
+ do { CProb *p = probs + res; RC_GET_BIT(p, res) } while(--i != 0); \
+ res -= (1 << numLevels); }
+
+
+#define kNumPosBitsMax 4
+#define kNumPosStatesMax (1 << kNumPosBitsMax)
+
+#define kLenNumLowBits 3
+#define kLenNumLowSymbols (1 << kLenNumLowBits)
+#define kLenNumMidBits 3
+#define kLenNumMidSymbols (1 << kLenNumMidBits)
+#define kLenNumHighBits 8
+#define kLenNumHighSymbols (1 << kLenNumHighBits)
+
+#define LenChoice 0
+#define LenChoice2 (LenChoice + 1)
+#define LenLow (LenChoice2 + 1)
+#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits))
+#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits))
+#define kNumLenProbs (LenHigh + kLenNumHighSymbols)
+
+
+#define kNumStates 12
+#define kNumLitStates 7
+
+#define kStartPosModelIndex 4
+#define kEndPosModelIndex 14
+#define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
+
+#define kNumPosSlotBits 6
+#define kNumLenToPosStates 4
+
+#define kNumAlignBits 4
+#define kAlignTableSize (1 << kNumAlignBits)
+
+#define kMatchMinLen 2
+
+#define IsMatch 0
+#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax))
+#define IsRepG0 (IsRep + kNumStates)
+#define IsRepG1 (IsRepG0 + kNumStates)
+#define IsRepG2 (IsRepG1 + kNumStates)
+#define IsRep0Long (IsRepG2 + kNumStates)
+#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax))
+#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits))
+#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex)
+#define LenCoder (Align + kAlignTableSize)
+#define RepLenCoder (LenCoder + kNumLenProbs)
+#define Literal (RepLenCoder + kNumLenProbs)
+
+#if Literal != LZMA_BASE_SIZE
+StopCompilingDueBUG
+#endif
+
+int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size)
+{
+ unsigned char prop0;
+ if (size < LZMA_PROPERTIES_SIZE)
+ return LZMA_RESULT_DATA_ERROR;
+ prop0 = propsData[0];
+ if (prop0 >= (9 * 5 * 5))
+ return LZMA_RESULT_DATA_ERROR;
+ {
+ for (propsRes->pb = 0; prop0 >= (9 * 5); propsRes->pb++, prop0 -= (9 * 5));
+ for (propsRes->lp = 0; prop0 >= 9; propsRes->lp++, prop0 -= 9);
+ propsRes->lc = prop0;
+ /*
+ unsigned char remainder = (unsigned char)(prop0 / 9);
+ propsRes->lc = prop0 % 9;
+ propsRes->pb = remainder / 5;
+ propsRes->lp = remainder % 5;
+ */
+ }
+
+ #ifdef _LZMA_OUT_READ
+ {
+ int i;
+ propsRes->DictionarySize = 0;
+ for (i = 0; i < 4; i++)
+ propsRes->DictionarySize += (UInt32)(propsData[1 + i]) << (i * 8);
+ if (propsRes->DictionarySize == 0)
+ propsRes->DictionarySize = 1;
+ }
+ #endif
+ return LZMA_RESULT_OK;
+}
+
+#define kLzmaStreamWasFinishedId (-1)
+
+int LzmaDecode(CLzmaDecoderState *vs,
+ #ifdef _LZMA_IN_CB
+ ILzmaInCallback *InCallback,
+ #else
+ const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed,
+ #endif
+ unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed)
+{
+ CProb *p = vs->Probs;
+ SizeT nowPos = 0;
+ Byte previousByte = 0;
+ UInt32 posStateMask = (1 << (vs->Properties.pb)) - 1;
+ UInt32 literalPosMask = (1 << (vs->Properties.lp)) - 1;
+ int lc = vs->Properties.lc;
+
+ #ifdef _LZMA_OUT_READ
+
+ UInt32 Range = vs->Range;
+ UInt32 Code = vs->Code;
+ #ifdef _LZMA_IN_CB
+ const Byte *Buffer = vs->Buffer;
+ const Byte *BufferLim = vs->BufferLim;
+ #else
+ const Byte *Buffer = inStream;
+ const Byte *BufferLim = inStream + inSize;
+ #endif
+ int state = vs->State;
+ UInt32 rep0 = vs->Reps[0], rep1 = vs->Reps[1], rep2 = vs->Reps[2], rep3 = vs->Reps[3];
+ int len = vs->RemainLen;
+ UInt32 globalPos = vs->GlobalPos;
+ UInt32 distanceLimit = vs->DistanceLimit;
+
+ Byte *dictionary = vs->Dictionary;
+ UInt32 dictionarySize = vs->Properties.DictionarySize;
+ UInt32 dictionaryPos = vs->DictionaryPos;
+
+ Byte tempDictionary[4];
+
+ #ifndef _LZMA_IN_CB
+ *inSizeProcessed = 0;
+ #endif
+ *outSizeProcessed = 0;
+ if (len == kLzmaStreamWasFinishedId)
+ return LZMA_RESULT_OK;
+
+ if (dictionarySize == 0)
+ {
+ dictionary = tempDictionary;
+ dictionarySize = 1;
+ tempDictionary[0] = vs->TempDictionary[0];
+ }
+
+ if (len == kLzmaNeedInitId)
+ {
+ {
+ UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp));
+ UInt32 i;
+ for (i = 0; i < numProbs; i++)
+ p[i] = kBitModelTotal >> 1;
+ rep0 = rep1 = rep2 = rep3 = 1;
+ state = 0;
+ globalPos = 0;
+ distanceLimit = 0;
+ dictionaryPos = 0;
+ dictionary[dictionarySize - 1] = 0;
+ #ifdef _LZMA_IN_CB
+ RC_INIT;
+ #else
+ RC_INIT(inStream, inSize);
+ #endif
+ }
+ len = 0;
+ }
+ while(len != 0 && nowPos < outSize)
+ {
+ UInt32 pos = dictionaryPos - rep0;
+ if (pos >= dictionarySize)
+ pos += dictionarySize;
+ outStream[nowPos++] = dictionary[dictionaryPos] = dictionary[pos];
+ if (++dictionaryPos == dictionarySize)
+ dictionaryPos = 0;
+ len--;
+ }
+ if (dictionaryPos == 0)
+ previousByte = dictionary[dictionarySize - 1];
+ else
+ previousByte = dictionary[dictionaryPos - 1];
+
+ #else /* if !_LZMA_OUT_READ */
+
+ int state = 0;
+ UInt32 rep0 = 1, rep1 = 1, rep2 = 1, rep3 = 1;
+ int len = 0;
+ const Byte *Buffer;
+ const Byte *BufferLim;
+ UInt32 Range;
+ UInt32 Code;
+
+ #ifndef _LZMA_IN_CB
+ *inSizeProcessed = 0;
+ #endif
+ *outSizeProcessed = 0;
+
+ {
+ UInt32 i;
+ UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp));
+ for (i = 0; i < numProbs; i++)
+ p[i] = kBitModelTotal >> 1;
+ }
+
+ #ifdef _LZMA_IN_CB
+ RC_INIT;
+ #else
+ RC_INIT(inStream, inSize);
+ #endif
+
+ #endif /* _LZMA_OUT_READ */
+
+ while(nowPos < outSize)
+ {
+ CProb *prob;
+ UInt32 bound;
+ int posState = (int)(
+ (nowPos
+ #ifdef _LZMA_OUT_READ
+ + globalPos
+ #endif
+ )
+ & posStateMask);
+
+ prob = p + IsMatch + (state << kNumPosBitsMax) + posState;
+ IfBit0(prob)
+ {
+ int symbol = 1;
+ UpdateBit0(prob)
+ prob = p + Literal + (LZMA_LIT_SIZE *
+ (((
+ (nowPos
+ #ifdef _LZMA_OUT_READ
+ + globalPos
+ #endif
+ )
+ & literalPosMask) << lc) + (previousByte >> (8 - lc))));
+
+ if (state >= kNumLitStates)
+ {
+ int matchByte;
+ #ifdef _LZMA_OUT_READ
+ UInt32 pos = dictionaryPos - rep0;
+ if (pos >= dictionarySize)
+ pos += dictionarySize;
+ matchByte = dictionary[pos];
+ #else
+ matchByte = outStream[nowPos - rep0];
+ #endif
+ do
+ {
+ int bit;
+ CProb *probLit;
+ matchByte <<= 1;
+ bit = (matchByte & 0x100);
+ probLit = prob + 0x100 + bit + symbol;
+ RC_GET_BIT2(probLit, symbol, if (bit != 0) break, if (bit == 0) break)
+ }
+ while (symbol < 0x100);
+ }
+ while (symbol < 0x100)
+ {
+ CProb *probLit = prob + symbol;
+ RC_GET_BIT(probLit, symbol)
+ }
+ previousByte = (Byte)symbol;
+
+ outStream[nowPos++] = previousByte;
+ #ifdef _LZMA_OUT_READ
+ if (distanceLimit < dictionarySize)
+ distanceLimit++;
+
+ dictionary[dictionaryPos] = previousByte;
+ if (++dictionaryPos == dictionarySize)
+ dictionaryPos = 0;
+ #endif
+ if (state < 4) state = 0;
+ else if (state < 10) state -= 3;
+ else state -= 6;
+ }
+ else
+ {
+ UpdateBit1(prob);
+ prob = p + IsRep + state;
+ IfBit0(prob)
+ {
+ UpdateBit0(prob);
+ rep3 = rep2;
+ rep2 = rep1;
+ rep1 = rep0;
+ state = state < kNumLitStates ? 0 : 3;
+ prob = p + LenCoder;
+ }
+ else
+ {
+ UpdateBit1(prob);
+ prob = p + IsRepG0 + state;
+ IfBit0(prob)
+ {
+ UpdateBit0(prob);
+ prob = p + IsRep0Long + (state << kNumPosBitsMax) + posState;
+ IfBit0(prob)
+ {
+ #ifdef _LZMA_OUT_READ
+ UInt32 pos;
+ #endif
+ UpdateBit0(prob);
+
+ #ifdef _LZMA_OUT_READ
+ if (distanceLimit == 0)
+ #else
+ if (nowPos == 0)
+ #endif
+ {
+ printf("distanceLimit == 0\n");
+ return LZMA_RESULT_DATA_ERROR;
+ }
+
+ state = state < kNumLitStates ? 9 : 11;
+ #ifdef _LZMA_OUT_READ
+ pos = dictionaryPos - rep0;
+ if (pos >= dictionarySize)
+ pos += dictionarySize;
+ previousByte = dictionary[pos];
+ dictionary[dictionaryPos] = previousByte;
+ if (++dictionaryPos == dictionarySize)
+ dictionaryPos = 0;
+ #else
+ previousByte = outStream[nowPos - rep0];
+ #endif
+ outStream[nowPos++] = previousByte;
+ #ifdef _LZMA_OUT_READ
+ if (distanceLimit < dictionarySize)
+ distanceLimit++;
+ #endif
+
+ continue;
+ }
+ else
+ {
+ UpdateBit1(prob);
+ }
+ }
+ else
+ {
+ UInt32 distance;
+ UpdateBit1(prob);
+ prob = p + IsRepG1 + state;
+ IfBit0(prob)
+ {
+ UpdateBit0(prob);
+ distance = rep1;
+ }
+ else
+ {
+ UpdateBit1(prob);
+ prob = p + IsRepG2 + state;
+ IfBit0(prob)
+ {
+ UpdateBit0(prob);
+ distance = rep2;
+ }
+ else
+ {
+ UpdateBit1(prob);
+ distance = rep3;
+ rep3 = rep2;
+ }
+ rep2 = rep1;
+ }
+ rep1 = rep0;
+ rep0 = distance;
+ }
+ state = state < kNumLitStates ? 8 : 11;
+ prob = p + RepLenCoder;
+ }
+ {
+ int numBits, offset;
+ CProb *probLen = prob + LenChoice;
+ IfBit0(probLen)
+ {
+ UpdateBit0(probLen);
+ probLen = prob + LenLow + (posState << kLenNumLowBits);
+ offset = 0;
+ numBits = kLenNumLowBits;
+ }
+ else
+ {
+ UpdateBit1(probLen);
+ probLen = prob + LenChoice2;
+ IfBit0(probLen)
+ {
+ UpdateBit0(probLen);
+ probLen = prob + LenMid + (posState << kLenNumMidBits);
+ offset = kLenNumLowSymbols;
+ numBits = kLenNumMidBits;
+ }
+ else
+ {
+ UpdateBit1(probLen);
+ probLen = prob + LenHigh;
+ offset = kLenNumLowSymbols + kLenNumMidSymbols;
+ numBits = kLenNumHighBits;
+ }
+ }
+ RangeDecoderBitTreeDecode(probLen, numBits, len);
+ len += offset;
+ }
+
+ if (state < 4)
+ {
+ int posSlot;
+ state += kNumLitStates;
+ prob = p + PosSlot +
+ ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) <<
+ kNumPosSlotBits);
+ RangeDecoderBitTreeDecode(prob, kNumPosSlotBits, posSlot);
+ if (posSlot >= kStartPosModelIndex)
+ {
+ int numDirectBits = ((posSlot >> 1) - 1);
+ rep0 = (2 | ((UInt32)posSlot & 1));
+ if (posSlot < kEndPosModelIndex)
+ {
+ rep0 <<= numDirectBits;
+ prob = p + SpecPos + rep0 - posSlot - 1;
+ }
+ else
+ {
+ numDirectBits -= kNumAlignBits;
+ do
+ {
+ RC_NORMALIZE
+ Range >>= 1;
+ rep0 <<= 1;
+ if (Code >= Range)
+ {
+ Code -= Range;
+ rep0 |= 1;
+ }
+ }
+ while (--numDirectBits != 0);
+ prob = p + Align;
+ rep0 <<= kNumAlignBits;
+ numDirectBits = kNumAlignBits;
+ }
+ {
+ int i = 1;
+ int mi = 1;
+ do
+ {
+ CProb *prob3 = prob + mi;
+ RC_GET_BIT2(prob3, mi, ; , rep0 |= i);
+ i <<= 1;
+ }
+ while(--numDirectBits != 0);
+ }
+ }
+ else
+ rep0 = posSlot;
+ if (++rep0 == (UInt32)(0))
+ {
+ /* it's for stream version */
+ len = kLzmaStreamWasFinishedId;
+ break;
+ }
+ }
+
+ len += kMatchMinLen;
+ #ifdef _LZMA_OUT_READ
+ if (rep0 > distanceLimit)
+ #else
+ if (rep0 > nowPos)
+ #endif
+ {
+ printf("rep0 %d > distanceLimit %d\n", rep0, distanceLimit);
+ return LZMA_RESULT_DATA_ERROR;
+ }
+
+ #ifdef _LZMA_OUT_READ
+ if (dictionarySize - distanceLimit > (UInt32)len)
+ distanceLimit += len;
+ else
+ distanceLimit = dictionarySize;
+ #endif
+
+ do
+ {
+ #ifdef _LZMA_OUT_READ
+ UInt32 pos = dictionaryPos - rep0;
+ if (pos >= dictionarySize)
+ pos += dictionarySize;
+ previousByte = dictionary[pos];
+ dictionary[dictionaryPos] = previousByte;
+ if (++dictionaryPos == dictionarySize)
+ dictionaryPos = 0;
+ #else
+ previousByte = outStream[nowPos - rep0];
+ #endif
+ len--;
+ outStream[nowPos++] = previousByte;
+ }
+ while(len != 0 && nowPos < outSize);
+ }
+ }
+ RC_NORMALIZE;
+
+ #ifdef _LZMA_OUT_READ
+ vs->Range = Range;
+ vs->Code = Code;
+ vs->DictionaryPos = dictionaryPos;
+ vs->GlobalPos = globalPos + (UInt32)nowPos;
+ vs->DistanceLimit = distanceLimit;
+ vs->Reps[0] = rep0;
+ vs->Reps[1] = rep1;
+ vs->Reps[2] = rep2;
+ vs->Reps[3] = rep3;
+ vs->State = state;
+ vs->RemainLen = len;
+ vs->TempDictionary[0] = tempDictionary[0];
+ #endif
+
+ #ifdef _LZMA_IN_CB
+ vs->Buffer = Buffer;
+ vs->BufferLim = BufferLim;
+ #else
+ *inSizeProcessed = (SizeT)(Buffer - inStream);
+ #endif
+ *outSizeProcessed = nowPos;
+ return LZMA_RESULT_OK;
+}
diff -Nru swftools-0.9.2+ds1/installer/lzma/LzmaDecode.h swftools-0.9.1/installer/lzma/LzmaDecode.h
--- swftools-0.9.2+ds1/installer/lzma/LzmaDecode.h 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/installer/lzma/LzmaDecode.h 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,114 @@
+/*
+ LzmaDecode.h
+ LZMA Decoder interface
+
+ LZMA SDK 4.40 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01)
+ http://www.7-zip.org/
+
+ LZMA SDK is licensed under two licenses:
+ 1) GNU Lesser General Public License (GNU LGPL)
+ 2) Common Public License (CPL)
+ It means that you can select one of these two licenses and
+ follow rules of that license.
+
+ SPECIAL EXCEPTION:
+ Igor Pavlov, as the author of this code, expressly permits you to
+ statically or dynamically link your code (or bind by name) to the
+ interfaces of this file without subjecting your linked code to the
+ terms of the CPL or GNU LGPL. Any modifications or additions
+ to this file, however, are subject to the LGPL or CPL terms.
+*/
+
+#ifndef __LZMADECODE_H
+#define __LZMADECODE_H
+
+#include "LzmaTypes.h"
+
+/* #define _LZMA_IN_CB */
+/* Use callback for input data */
+
+#define _LZMA_OUT_READ
+/* Use read function for output data */
+
+/* #define _LZMA_PROB32 */
+/* It can increase speed on some 32-bit CPUs,
+ but memory usage will be doubled in that case */
+
+/* #define _LZMA_LOC_OPT */
+/* Enable local speed optimizations inside code */
+
+#ifdef _LZMA_PROB32
+#define CProb UInt32
+#else
+#define CProb UInt16
+#endif
+
+
+#define LZMA_RESULT_OK 0
+#define LZMA_RESULT_DATA_ERROR 1
+
+#ifdef _LZMA_IN_CB
+typedef struct _ILzmaInCallback
+{
+ int (*Read)(void *object, const unsigned char **buffer, SizeT *bufferSize);
+} ILzmaInCallback;
+#endif
+
+#define LZMA_BASE_SIZE 1846
+#define LZMA_LIT_SIZE 768
+
+#define LZMA_PROPERTIES_SIZE 5
+
+typedef struct _CLzmaProperties
+{
+ int lc;
+ int lp;
+ int pb;
+ #ifdef _LZMA_OUT_READ
+ UInt32 DictionarySize;
+ #endif
+}CLzmaProperties;
+
+int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size);
+
+#define LzmaGetNumProbs(Properties) (LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((Properties)->lc + (Properties)->lp)))
+
+#define kLzmaNeedInitId (-2)
+
+typedef struct _CLzmaDecoderState
+{
+ CLzmaProperties Properties;
+ CProb *Probs;
+
+ #ifdef _LZMA_IN_CB
+ const unsigned char *Buffer;
+ const unsigned char *BufferLim;
+ #endif
+
+ #ifdef _LZMA_OUT_READ
+ unsigned char *Dictionary;
+ UInt32 Range;
+ UInt32 Code;
+ UInt32 DictionaryPos;
+ UInt32 GlobalPos;
+ UInt32 DistanceLimit;
+ UInt32 Reps[4];
+ int State;
+ int RemainLen;
+ unsigned char TempDictionary[4];
+ #endif
+} CLzmaDecoderState;
+
+#ifdef _LZMA_OUT_READ
+#define LzmaDecoderInit(vs) { (vs)->RemainLen = kLzmaNeedInitId; }
+#endif
+
+int LzmaDecode(CLzmaDecoderState *vs,
+ #ifdef _LZMA_IN_CB
+ ILzmaInCallback *inCallback,
+ #else
+ const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed,
+ #endif
+ unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed);
+
+#endif
diff -Nru swftools-0.9.2+ds1/installer/lzma/LzmaTypes.h swftools-0.9.1/installer/lzma/LzmaTypes.h
--- swftools-0.9.2+ds1/installer/lzma/LzmaTypes.h 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/installer/lzma/LzmaTypes.h 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,45 @@
+/*
+LzmaTypes.h
+
+Types for LZMA Decoder
+
+This file written and distributed to public domain by Igor Pavlov.
+This file is part of LZMA SDK 4.40 (2006-05-01)
+*/
+
+#ifndef __LZMATYPES_H
+#define __LZMATYPES_H
+
+#ifndef _7ZIP_BYTE_DEFINED
+#define _7ZIP_BYTE_DEFINED
+typedef unsigned char Byte;
+#endif
+
+#ifndef _7ZIP_UINT16_DEFINED
+#define _7ZIP_UINT16_DEFINED
+typedef unsigned short UInt16;
+#endif
+
+#ifndef _7ZIP_UINT32_DEFINED
+#define _7ZIP_UINT32_DEFINED
+#ifdef _LZMA_UINT32_IS_ULONG
+typedef unsigned long UInt32;
+#else
+typedef unsigned int UInt32;
+#endif
+#endif
+
+/* #define _LZMA_NO_SYSTEM_SIZE_T */
+/* You can use it, if you don't want */
+
+#ifndef _7ZIP_SIZET_DEFINED
+#define _7ZIP_SIZET_DEFINED
+#ifdef _LZMA_NO_SYSTEM_SIZE_T
+typedef UInt32 SizeT;
+#else
+#include
+typedef size_t SizeT;
+#endif
+#endif
+
+#endif
diff -Nru swftools-0.9.2+ds1/installer/Makefile swftools-0.9.1/installer/Makefile
--- swftools-0.9.2+ds1/installer/Makefile 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/installer/Makefile 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,74 @@
+CC=i686-pc-mingw32-gcc -DWIN32 -Wno-trigraphs
+STRIP=i686-pc-mingw32-strip
+WINDRES=i686-pc-mingw32-windres
+
+LICENSE=gpl.c
+
+all: files1.exe uninstall.exe mkarchive
+
+LIBS=-lgdi32 -lshlwapi -lcomctl32 -lshell32 -lole32 -luuid
+
+files1.c: ../win32/*.exe mkarchive uninstall.exe
+ cp uninstall.exe ../win32/
+ CWD=`pwd`
+ cd ../win32;../installer/mkarchive `find`
+ mv ../win32/crnfiles.c ./files1.c
+
+#files2.c: ../win32_gui/*.exe ../win32_gui/*.swf mkarchive uninstall.exe
+# cp uninstall.exe ../win32_gui/
+# CWD=`pwd`
+# cd ../win32_gui;../installer/mkarchive `find`
+# mv ../win32_gui/crnfiles.c ./files2.c
+
+%.o: %.c
+ $(CC) -c $<
+
+mkarchive: mkarchive.c
+ gcc mkarchive.c -o mkarchive -lz
+
+crnfiles1.o: crnfiles1.c
+#crnfiles2.o: crnfiles2.c
+
+#depack.o: depack.c depack.h Makefile
+# $(CC) -c depack.c -o depack.o
+
+archive.o: archive.c archive.c
+ $(CC) -c archive.c -o archive.o
+
+utils.o: utils.c utils.c
+ $(CC) -c utils.c -o utils.o
+
+license.o: $(LICENSE)
+ $(CC) -c $< -o license.o
+
+installer.o: installer.c installer.h archive.h
+ $(CC) -c installer.c -o installer.o
+
+uninstaller.o: installer.c installer.h
+ $(CC) -DDEINSTALL -c installer.c -o uninstaller.o
+
+installer.coff: installer.rc swftools.ico installer.h
+ $(WINDRES) installer.rc -O coff -F pe-i386 -o installer.coff
+
+lzma/LzmaDecode.o: lzma/LzmaDecode.c lzma/LzmaDecode.h lzma/LzmaTypes.h
+ $(CC) -c lzma/LzmaDecode.c -o lzma/LzmaDecode.o
+
+uninstall.exe: uninstaller.o utils.o installer.coff Makefile
+ $(CC) uninstaller.o utils.o installer.coff -o $@ $(LIBS)
+ $(STRIP) $@
+ ./makegui $@
+ #upx -9 --best $@ 2>/dev/null || true
+
+%.exe: %.o installer.o license.o archive.o utils.o lzma/LzmaDecode.o installer.coff Makefile
+ $(CC) installer.o license.o utils.o archive.o lzma/LzmaDecode.o installer.coff $< -o $@ $(LIBS)
+ $(STRIP) $@
+ ./makegui $@
+
+#installer.exe: installer.c depack.o archive.o depack.h crnfiles.o installer.coff Makefile
+# $(CC) installer.c depack.o archive.o crnfiles.o installer.coff -o installer.exe $(LIBS)
+# $(STRIP) installer.exe
+# #./makegui installer.exe
+# #upx -9 --best installer.exe 2>/dev/null || true
+
+clean:
+ rm -f installer.exe files*exe crnfiles.c *.o *.coff
diff -Nru swftools-0.9.2+ds1/installer/makegui.c swftools-0.9.1/installer/makegui.c
--- swftools-0.9.2+ds1/installer/makegui.c 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/installer/makegui.c 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,53 @@
+/* makegui.c
+
+ Small program to set the gui flag in Win32 executables.
+
+ Copyright (c) 2004 Matthias Kramm
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include
+#include
+
+int main(int argn, char*argv[])
+{
+ char flag = 2;
+ FILE*fi = fopen(argv[1], "rb+");
+ if(argn<2) {
+ printf("Usage:\n");
+ printf("\t%s program.exe [console]\n", argv[0]);
+ return 0;
+ }
+ if(argn==3) {
+ if(!strcmp(argv[2], "console")) {
+ flag = 3;
+ }
+ }
+
+ if(!fi) {
+ perror(argv[1]);
+ exit(1);
+ }
+ fseek(fi,220,SEEK_SET);
+ if(flag == 2)
+ printf("Setting Win32 GUI flag in %s\n", argv[1]);
+ else if(flag == 3)
+ printf("Setting Win32 Console flag in %s\n", argv[1]);
+
+ fwrite(&flag, 1, 1, fi);
+ fclose(fi);
+ return 0;
+}
+
diff -Nru swftools-0.9.2+ds1/installer/mkarchive.c swftools-0.9.1/installer/mkarchive.c
--- swftools-0.9.2+ds1/installer/mkarchive.c 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/installer/mkarchive.c 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,434 @@
+/* mkarchive.c
+
+ Part of the rfx installer (Main program).
+
+ Copyright (c) 2004-2008 Matthias Kramm
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#define ZLIB_BUFFER_SIZE 16384
+
+typedef struct _writer
+{
+ int (*write)(struct _writer*, void*data, int len);
+ void (*finish)(struct _writer*);
+ void *internal;
+} writer_t;
+
+/* ---------------------------- file writer ------------------------------- */
+
+typedef struct
+{
+ FILE*fi;
+} filewrite_t;
+static int writer_filewrite_write(writer_t*w, void* data, int len)
+{
+ filewrite_t * fw= (filewrite_t*)w->internal;
+ return fwrite(data, len, 1, fw->fi);
+}
+static void writer_filewrite_finish(writer_t*w)
+{
+ filewrite_t *mr = (filewrite_t*)w->internal;
+ fclose(mr->fi);
+ free(w->internal);
+ memset(w, 0, sizeof(writer_t));
+}
+writer_t*writer_init_filewriter(char*filename)
+{
+ writer_t*w = malloc(sizeof(writer_t));
+ FILE*fi = fopen(filename, "wb");
+ if(!fi) {
+ perror(filename);
+ return 0;
+ }
+ filewrite_t *mr = (filewrite_t *)malloc(sizeof(filewrite_t));
+ mr->fi = fi;
+ memset(w, 0, sizeof(writer_t));
+ w->write = writer_filewrite_write;
+ w->finish = writer_filewrite_finish;
+ w->internal = mr;
+ return w;
+}
+
+/* ---------------------------- include file filter ------------------------------- */
+
+typedef struct _ifwrite
+{
+ FILE*fi;
+ int bp;
+ int pos;
+ int last;
+ char buf[1024];
+ char*filename;
+} ifwrite_t;
+
+static int writer_ifwrite_write(writer_t*out, void*data, int len)
+{
+ ifwrite_t*i = (ifwrite_t*)out->internal;
+ FILE*fo = i->fi;
+ int t;
+ for(t=0;tbp>=80) {
+ fprintf(fo, "\"%s\"\n", i->buf);
+ i->bp = 0;
+ }
+ if(c<=32 || c>0x7e || c=='"' || c == '\\' || c == '%'
+ || (i->last && c>='0' && c<='9')
+ || (i->last && c>='a' && c<='f')
+ || (i->last && c>='A' && c<='F')
+ ) {
+ i->bp += sprintf(i->buf+i->bp, "\\x%x",c);
+ i->last = 1;
+ } else {
+ i->buf[i->bp] = c;
+ i->buf[i->bp+1] = 0;
+ i->last = 0;
+ i->bp++;
+ }
+ i->pos++;
+ }
+}
+static void writer_ifwrite_finish(writer_t*w)
+{
+ ifwrite_t *i= (ifwrite_t*)w->internal;
+ fprintf(i->fi, "\"%s\"\n", i->buf);
+ fprintf(i->fi, ";\n");
+ fprintf(i->fi, "int crndata_len = %d;\n", i->pos);
+ fclose(i->fi);
+ printf("wrote file %s\n", i->filename);
+ free(w->internal);w->internal = 0;
+}
+
+writer_t*writer_init_includewriter(char*filename)
+{
+ writer_t*w = malloc(sizeof(writer_t));
+ FILE*fi = fopen(filename, "wb");
+ memset(w, 0, sizeof(writer_t));
+ w->write = writer_ifwrite_write;
+ w->finish = writer_ifwrite_finish;
+ ifwrite_t*i = (ifwrite_t *)malloc(sizeof(ifwrite_t));
+ i->fi = fi;
+ i->pos = 0;
+ i->bp=0;
+ i->last = 0;
+ i->filename = filename;
+ w->internal = i;
+
+ fprintf(i->fi, "char* crndata =\n");
+ return w;
+
+}
+
+/* ---------------------------- zlibdeflate writer -------------------------- */
+
+struct zlibdeflate_t
+{
+ z_stream zs;
+ writer_t*output;
+ int written;
+ int zwritten;
+ unsigned char writebuffer[ZLIB_BUFFER_SIZE];
+};
+
+static void zlib_error(int ret, char* msg, z_stream*zs)
+{
+ fprintf(stderr, "%s: zlib error (%d): last zlib error: %s\n",
+ msg,
+ ret,
+ zs->msg?zs->msg:"unknown");
+ perror("errno:");
+ exit(1);
+}
+
+static int writer_zlibdeflate_write(writer_t*writer, void* data, int len)
+{
+ struct zlibdeflate_t*z = (struct zlibdeflate_t*)writer->internal;
+ int ret;
+
+ if(!z) {
+ fprintf(stderr, "zlib not initialized!\n");
+ return 0;
+ }
+ if(!len)
+ return 0;
+
+ z->zs.next_in = (Bytef *)data;
+ z->zs.avail_in = len;
+
+ while(1) {
+ ret = deflate(&z->zs, Z_NO_FLUSH);
+
+ if (ret != Z_OK) zlib_error(ret, "bitio:deflate_deflate", &z->zs);
+
+ if(z->zs.next_out != z->writebuffer) {
+ z->zwritten += z->zs.next_out - (Bytef*)z->writebuffer;
+ z->output->write(z->output, z->writebuffer, z->zs.next_out - (Bytef*)z->writebuffer);
+ z->zs.next_out = z->writebuffer;
+ z->zs.avail_out = ZLIB_BUFFER_SIZE;
+ }
+
+ if(!z->zs.avail_in) {
+ break;
+ }
+ }
+ z->written += len;
+ return len;
+}
+static void writer_zlibdeflate_finish(writer_t*writer)
+{
+ struct zlibdeflate_t*z = (struct zlibdeflate_t*)writer->internal;
+ writer_t*output;
+ int ret;
+ if(!z)
+ return;
+ output= z->output;
+ while(1) {
+ ret = deflate(&z->zs, Z_FINISH);
+ if (ret != Z_OK &&
+ ret != Z_STREAM_END) zlib_error(ret, "bitio:deflate_finish", &z->zs);
+
+ if(z->zs.next_out != z->writebuffer) {
+ z->zwritten += z->zs.next_out - (Bytef*)z->writebuffer;
+ z->output->write(z->output, z->writebuffer, z->zs.next_out - (Bytef*)z->writebuffer);
+ z->zs.next_out = z->writebuffer;
+ z->zs.avail_out = ZLIB_BUFFER_SIZE;
+ }
+
+ if (ret == Z_STREAM_END) {
+ break;
+
+ }
+ }
+ ret = deflateEnd(&z->zs);
+ if (ret != Z_OK) zlib_error(ret, "bitio:deflate_end", &z->zs);
+
+ if(z->written) {
+ printf("Compression ratio: %.2f%% (%d bytes of input data, %d bytes of output data)\n",
+ z->zwritten*100.0 / z->written,
+ z->written, z->zwritten);
+ } else {
+ printf("Compression ratio: 0%% (0 bytes of input data, %d bytes of output data)\n", z->zwritten);
+ }
+
+ free(writer->internal);
+ memset(writer, 0, sizeof(writer_t));
+ output->finish(output);
+}
+writer_t*writer_init_zwriter(writer_t*output)
+{
+ writer_t*w = malloc(sizeof(writer_t));
+ struct zlibdeflate_t*z;
+ int ret;
+ memset(w, 0, sizeof(writer_t));
+ z = (struct zlibdeflate_t*)malloc(sizeof(struct zlibdeflate_t));
+ memset(z, 0, sizeof(struct zlibdeflate_t));
+ w->internal = z;
+ w->write = writer_zlibdeflate_write;
+ w->finish = writer_zlibdeflate_finish;
+ z->output = output;
+ memset(&z->zs,0,sizeof(z_stream));
+ z->zs.zalloc = Z_NULL;
+ z->zs.zfree = Z_NULL;
+ z->zs.opaque = Z_NULL;
+ ret = deflateInit(&z->zs, 9);
+ if (ret != Z_OK) zlib_error(ret, "bitio:deflate_init", &z->zs);
+ z->zs.next_out = z->writebuffer;
+ z->zs.avail_out = ZLIB_BUFFER_SIZE;
+ z->written = 0;
+ z->zwritten = 0;
+ return w;
+}
+
+/* ------------------------------- main ----------- ------------------------------- */
+
+static int compare_filenames(const void*_n1, const void*_n2)
+{
+ const char*s1 = *(const char**)_n1;
+ const char*s2 = *(const char**)_n2;
+
+ char*e1 = strrchr(s1, '.');
+ char*e2 = strrchr(s2, '.');
+ if(!e1 && !e2)
+ return 0;
+ if(e1 && !e2)
+ return 1;
+ if(!e1 && e2)
+ return -1;
+ int c = strcasecmp(e1+1,e2+1);
+ if(c)
+ return c;
+ return strcasecmp(s1,s2);
+}
+
+int main (int argn, char*argv[])
+{
+ int t;
+ char buf[320];
+ int num = 0;
+
+ int fullsize = 0;
+ for(t=1;t>8;
+ unsigned char n3=num>>16;
+ unsigned char n4=num>>24;
+ zwriter->write(zwriter,&n1,1);
+ zwriter->write(zwriter,&n2,1);
+ zwriter->write(zwriter,&n3,1);
+ zwriter->write(zwriter,&n4,1);
+
+ qsort(argv+1, argn-1, sizeof(argv[0]), compare_filenames);
+
+ for(t=1;twrite(zwriter,id,3);
+ unsigned char b1=l;
+ unsigned char b2=l>>8;
+ unsigned char b3=l>>16;
+ unsigned char b4=l>>24;
+ zwriter->write(zwriter,&b1,1);
+ zwriter->write(zwriter,&b2,1);
+ zwriter->write(zwriter,&b3,1);
+ zwriter->write(zwriter,&b4,1);
+ int sl=strlen(argv[t]);
+ if(sl>255) {
+ fprintf(stderr, "Error: filename %s too long\n", argv[t]);
+ }
+ unsigned char b = sl;
+ zwriter->write(zwriter,&b,1); //write filename len
+ zwriter->write(zwriter,argv[t],sl); //write filename
+ zwriter->write(zwriter,buf,l); //write data
+ fprintf(stderr,"[%s] %s: %d bytes written.\n", id, argv[t], l);
+ fclose(fi);
+ free(buf);
+ }
+ else
+ {
+ fprintf(stderr,"%s not found.\n", argv[t]);
+ }
+ }
+ }
+ char*id_end = "END";
+ zwriter->write(zwriter,id_end,3);
+ zwriter->finish(zwriter);
+
+#ifndef ZLIB
+ if(system("do_lzma e crnfiles.dat crnfiles.7z")&0xff00) {
+ perror("do_lzma");
+ exit(1);
+ }
+ FILE*fi = fopen("crnfiles.7z", "rb");
+ if(!fi) {
+ perror("crnfiles.7z");
+ exit(1);
+ }
+ writer_t*w = writer_init_includewriter("crnfiles.c");
+ while(!feof(fi)) {
+ char buf[4096];
+ int len = fread(buf,1,4096,fi);
+ if(!len)
+ break;
+ w->write(w, buf, len);
+ }
+ w->finish(w);
+ fclose(fi);
+ if(unlink("crnfiles.dat")) {
+ perror("crnfiles.dat");
+ exit(1);
+ }
+ if(unlink("crnfiles.7z")) {
+ perror("crnfiles.7z");
+ exit(1);
+ }
+#endif
+
+ fi = fopen("crnfiles.c", "ab+");
+ fprintf(fi, "\nint crn_decompressed_size=%d;\n", fullsize);
+ fclose(fi);
+
+ return 0;
+}
+
Binary files /tmp/5etvnGBqHs/swftools-0.9.2+ds1/installer/swftools.bmp and /tmp/M5qDI_SGQH/swftools-0.9.1/installer/swftools.bmp differ
Binary files /tmp/5etvnGBqHs/swftools-0.9.2+ds1/installer/swftools.ico and /tmp/M5qDI_SGQH/swftools-0.9.1/installer/swftools.ico differ
diff -Nru swftools-0.9.2+ds1/installer/utils.c swftools-0.9.1/installer/utils.c
--- swftools-0.9.2+ds1/installer/utils.c 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/installer/utils.c 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,18 @@
+char* concatPaths(const char*base, const char*add)
+{
+ int l1 = strlen(base);
+ int l2 = strlen(add);
+ int pos = 0;
+ char*n = 0;
+ while(l1 && base[l1-1] == '\\')
+ l1--;
+ while(pos < l2 && add[pos] == '\\')
+ pos++;
+
+ n = (char*)malloc(l1 + (l2-pos) + 2);
+ memcpy(n,base,l1);
+ n[l1]='\\';
+ strcpy(&n[l1+1],&add[pos]);
+ return n;
+}
+
diff -Nru swftools-0.9.2+ds1/installer/utils.h swftools-0.9.1/installer/utils.h
--- swftools-0.9.2+ds1/installer/utils.h 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/installer/utils.h 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,4 @@
+#ifndef __utils_h__
+#define __utils_h__
+char* concatPaths(const char*base, const char*add);
+#endif
diff -Nru swftools-0.9.2+ds1/lib/art/art_affine.c swftools-0.9.1/lib/art/art_affine.c
--- swftools-0.9.2+ds1/lib/art/art_affine.c 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/art/art_affine.c 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,458 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/* Simple manipulations with affine transformations */
+
+#include "config.h"
+#include "art_affine.h"
+#include "art_misc.h" /* for M_PI */
+
+#include
+#include /* for sprintf */
+#include /* for strcpy */
+
+
+/* According to a strict interpretation of the libart structure, this
+ routine should go into its own module, art_point_affine. However,
+ it's only two lines of code, and it can be argued that it is one of
+ the natural basic functions of an affine transformation.
+*/
+
+/**
+ * art_affine_point: Do an affine transformation of a point.
+ * @dst: Where the result point is stored.
+ * @src: The original point.
+ @ @affine: The affine transformation.
+ **/
+void
+art_affine_point (ArtPoint *dst, const ArtPoint *src,
+ const double affine[6])
+{
+ double x, y;
+
+ x = src->x;
+ y = src->y;
+ dst->x = x * affine[0] + y * affine[2] + affine[4];
+ dst->y = x * affine[1] + y * affine[3] + affine[5];
+}
+
+/**
+ * art_affine_invert: Find the inverse of an affine transformation.
+ * @dst: Where the resulting affine is stored.
+ * @src: The original affine transformation.
+ *
+ * All non-degenerate affine transforms are invertible. If the original
+ * affine is degenerate or nearly so, expect numerical instability and
+ * very likely core dumps on Alpha and other fp-picky architectures.
+ * Otherwise, @dst multiplied with @src, or @src multiplied with @dst
+ * will be (to within roundoff error) the identity affine.
+ **/
+void
+art_affine_invert (double dst[6], const double src[6])
+{
+ double r_det;
+
+ r_det = 1.0 / (src[0] * src[3] - src[1] * src[2]);
+ dst[0] = src[3] * r_det;
+ dst[1] = -src[1] * r_det;
+ dst[2] = -src[2] * r_det;
+ dst[3] = src[0] * r_det;
+ dst[4] = -src[4] * dst[0] - src[5] * dst[2];
+ dst[5] = -src[4] * dst[1] - src[5] * dst[3];
+}
+
+/**
+ * art_affine_flip: Flip an affine transformation horizontally and/or vertically.
+ * @dst_affine: Where the resulting affine is stored.
+ * @src_affine: The original affine transformation.
+ * @horiz: Whether or not to flip horizontally.
+ * @vert: Whether or not to flip horizontally.
+ *
+ * Flips the affine transform. FALSE for both @horiz and @vert implements
+ * a simple copy operation. TRUE for both @horiz and @vert is a
+ * 180 degree rotation. It is ok for @src_affine and @dst_affine to
+ * be equal pointers.
+ **/
+void
+art_affine_flip (double dst_affine[6], const double src_affine[6], int horz, int vert)
+{
+ dst_affine[0] = horz ? - src_affine[0] : src_affine[0];
+ dst_affine[1] = horz ? - src_affine[1] : src_affine[1];
+ dst_affine[2] = vert ? - src_affine[2] : src_affine[2];
+ dst_affine[3] = vert ? - src_affine[3] : src_affine[3];
+ dst_affine[4] = horz ? - src_affine[4] : src_affine[4];
+ dst_affine[5] = vert ? - src_affine[5] : src_affine[5];
+}
+
+#define EPSILON 1e-6
+
+/* It's ridiculous I have to write this myself. This is hardcoded to
+ six digits of precision, which is good enough for PostScript.
+
+ The return value is the number of characters (i.e. strlen (str)).
+ It is no more than 12. */
+static int
+art_ftoa (char str[80], double x)
+{
+ char *p = str;
+ int i, j;
+
+ p = str;
+ if (fabs (x) < EPSILON / 2)
+ {
+ strcpy (str, "0");
+ return 1;
+ }
+ if (x < 0)
+ {
+ *p++ = '-';
+ x = -x;
+ }
+ if ((int)floor ((x + EPSILON / 2) < 1))
+ {
+ *p++ = '0';
+ *p++ = '.';
+ i = sprintf (p, "%06d", (int)floor ((x + EPSILON / 2) * 1e6));
+ while (i && p[i - 1] == '0')
+ i--;
+ if (i == 0)
+ i--;
+ p += i;
+ }
+ else if (x < 1e6)
+ {
+ i = sprintf (p, "%d", (int)floor (x + EPSILON / 2));
+ p += i;
+ if (i < 6)
+ {
+ int ix;
+
+ *p++ = '.';
+ x -= floor (x + EPSILON / 2);
+ for (j = i; j < 6; j++)
+ x *= 10;
+ ix = floor (x + 0.5);
+
+ for (j = 0; j < i; j++)
+ ix *= 10;
+
+ /* A cheap hack, this routine can round wrong for fractions
+ near one. */
+ if (ix == 1000000)
+ ix = 999999;
+
+ sprintf (p, "%06d", ix);
+ i = 6 - i;
+ while (i && p[i - 1] == '0')
+ i--;
+ if (i == 0)
+ i--;
+ p += i;
+ }
+ }
+ else
+ p += sprintf (p, "%g", x);
+
+ *p = '\0';
+ return p - str;
+}
+
+
+
+#include
+/**
+ * art_affine_to_string: Convert affine transformation to concise PostScript string representation.
+ * @str: Where to store the resulting string.
+ * @src: The affine transform.
+ *
+ * Converts an affine transform into a bit of PostScript code that
+ * implements the transform. Special cases of scaling, rotation, and
+ * translation are detected, and the corresponding PostScript
+ * operators used (this greatly aids understanding the output
+ * generated). The identity transform is mapped to the null string.
+ **/
+void
+art_affine_to_string (char str[128], const double src[6])
+{
+ char tmp[80];
+ int i, ix;
+
+#if 0
+ for (i = 0; i < 1000; i++)
+ {
+ double d = rand () * .1 / RAND_MAX;
+ art_ftoa (tmp, d);
+ printf ("%g %f %s\n", d, d, tmp);
+ }
+#endif
+ if (fabs (src[4]) < EPSILON && fabs (src[5]) < EPSILON)
+ {
+ /* could be scale or rotate */
+ if (fabs (src[1]) < EPSILON && fabs (src[2]) < EPSILON)
+ {
+ /* scale */
+ if (fabs (src[0] - 1) < EPSILON && fabs (src[3] - 1) < EPSILON)
+ {
+ /* identity transform */
+ str[0] = '\0';
+ return;
+ }
+ else
+ {
+ ix = 0;
+ ix += art_ftoa (str + ix, src[0]);
+ str[ix++] = ' ';
+ ix += art_ftoa (str + ix, src[3]);
+ strcpy (str + ix, " scale");
+ return;
+ }
+ }
+ else
+ {
+ /* could be rotate */
+ if (fabs (src[0] - src[3]) < EPSILON &&
+ fabs (src[1] + src[2]) < EPSILON &&
+ fabs (src[0] * src[0] + src[1] * src[1] - 1) < 2 * EPSILON)
+ {
+ double theta;
+
+ theta = (180 / M_PI) * atan2 (src[1], src[0]);
+ art_ftoa (tmp, theta);
+ sprintf (str, "%s rotate", tmp);
+ return;
+ }
+ }
+ }
+ else
+ {
+ /* could be translate */
+ if (fabs (src[0] - 1) < EPSILON && fabs (src[1]) < EPSILON &&
+ fabs (src[2]) < EPSILON && fabs (src[3] - 1) < EPSILON)
+ {
+ ix = 0;
+ ix += art_ftoa (str + ix, src[4]);
+ str[ix++] = ' ';
+ ix += art_ftoa (str + ix, src[5]);
+ strcpy (str + ix, " translate");
+ return;
+ }
+ }
+
+ ix = 0;
+ str[ix++] = '[';
+ str[ix++] = ' ';
+ for (i = 0; i < 6; i++)
+ {
+ ix += art_ftoa (str + ix, src[i]);
+ str[ix++] = ' ';
+ }
+ strcpy (str + ix, "] concat");
+}
+
+/**
+ * art_affine_multiply: Multiply two affine transformation matrices.
+ * @dst: Where to store the result.
+ * @src1: The first affine transform to multiply.
+ * @src2: The second affine transform to multiply.
+ *
+ * Multiplies two affine transforms together, i.e. the resulting @dst
+ * is equivalent to doing first @src1 then @src2. Note that the
+ * PostScript concat operator multiplies on the left, i.e. "M concat"
+ * is equivalent to "CTM = multiply (M, CTM)";
+ *
+ * It is safe to call this function with @dst equal to @src1 or @src2.
+ **/
+void
+art_affine_multiply (double dst[6], const double src1[6], const double src2[6])
+{
+ double d0, d1, d2, d3, d4, d5;
+
+ d0 = src1[0] * src2[0] + src1[1] * src2[2];
+ d1 = src1[0] * src2[1] + src1[1] * src2[3];
+ d2 = src1[2] * src2[0] + src1[3] * src2[2];
+ d3 = src1[2] * src2[1] + src1[3] * src2[3];
+ d4 = src1[4] * src2[0] + src1[5] * src2[2] + src2[4];
+ d5 = src1[4] * src2[1] + src1[5] * src2[3] + src2[5];
+ dst[0] = d0;
+ dst[1] = d1;
+ dst[2] = d2;
+ dst[3] = d3;
+ dst[4] = d4;
+ dst[5] = d5;
+}
+
+/**
+ * art_affine_identity: Set up the identity matrix.
+ * @dst: Where to store the resulting affine transform.
+ *
+ * Sets up an identity matrix.
+ **/
+void
+art_affine_identity (double dst[6])
+{
+ dst[0] = 1;
+ dst[1] = 0;
+ dst[2] = 0;
+ dst[3] = 1;
+ dst[4] = 0;
+ dst[5] = 0;
+}
+
+
+/**
+ * art_affine_scale: Set up a scaling matrix.
+ * @dst: Where to store the resulting affine transform.
+ * @sx: X scale factor.
+ * @sy: Y scale factor.
+ *
+ * Sets up a scaling matrix.
+ **/
+void
+art_affine_scale (double dst[6], double sx, double sy)
+{
+ dst[0] = sx;
+ dst[1] = 0;
+ dst[2] = 0;
+ dst[3] = sy;
+ dst[4] = 0;
+ dst[5] = 0;
+}
+
+/**
+ * art_affine_rotate: Set up a rotation affine transform.
+ * @dst: Where to store the resulting affine transform.
+ * @theta: Rotation angle in degrees.
+ *
+ * Sets up a rotation matrix. In the standard libart coordinate
+ * system, in which increasing y moves downward, this is a
+ * counterclockwise rotation. In the standard PostScript coordinate
+ * system, which is reversed in the y direction, it is a clockwise
+ * rotation.
+ **/
+void
+art_affine_rotate (double dst[6], double theta)
+{
+ double s, c;
+
+ s = sin (theta * M_PI / 180.0);
+ c = cos (theta * M_PI / 180.0);
+ dst[0] = c;
+ dst[1] = s;
+ dst[2] = -s;
+ dst[3] = c;
+ dst[4] = 0;
+ dst[5] = 0;
+}
+
+/**
+ * art_affine_shear: Set up a shearing matrix.
+ * @dst: Where to store the resulting affine transform.
+ * @theta: Shear angle in degrees.
+ *
+ * Sets up a shearing matrix. In the standard libart coordinate system
+ * and a small value for theta, || becomes \\. Horizontal lines remain
+ * unchanged.
+ **/
+void
+art_affine_shear (double dst[6], double theta)
+{
+ double t;
+
+ t = tan (theta * M_PI / 180.0);
+ dst[0] = 1;
+ dst[1] = 0;
+ dst[2] = t;
+ dst[3] = 1;
+ dst[4] = 0;
+ dst[5] = 0;
+}
+
+/**
+ * art_affine_translate: Set up a translation matrix.
+ * @dst: Where to store the resulting affine transform.
+ * @tx: X translation amount.
+ * @tx: Y translation amount.
+ *
+ * Sets up a translation matrix.
+ **/
+void
+art_affine_translate (double dst[6], double tx, double ty)
+{
+ dst[0] = 1;
+ dst[1] = 0;
+ dst[2] = 0;
+ dst[3] = 1;
+ dst[4] = tx;
+ dst[5] = ty;
+}
+
+/**
+ * art_affine_expansion: Find the affine's expansion factor.
+ * @src: The affine transformation.
+ *
+ * Finds the expansion factor, i.e. the square root of the factor
+ * by which the affine transform affects area. In an affine transform
+ * composed of scaling, rotation, shearing, and translation, returns
+ * the amount of scaling.
+ *
+ * Return value: the expansion factor.
+ **/
+double
+art_affine_expansion (const double src[6])
+{
+ return sqrt (fabs (src[0] * src[3] - src[1] * src[2]));
+}
+
+/**
+ * art_affine_rectilinear: Determine whether the affine transformation is rectilinear.
+ * @src: The original affine transformation.
+ *
+ * Determines whether @src is rectilinear, i.e. grid-aligned
+ * rectangles are transformed to other grid-aligned rectangles. The
+ * implementation has epsilon-tolerance for roundoff errors.
+ *
+ * Return value: TRUE if @src is rectilinear.
+ **/
+int
+art_affine_rectilinear (const double src[6])
+{
+ return ((fabs (src[1]) < EPSILON && fabs (src[2]) < EPSILON) ||
+ (fabs (src[0]) < EPSILON && fabs (src[3]) < EPSILON));
+}
+
+/**
+ * art_affine_equal: Determine whether two affine transformations are equal.
+ * @matrix1: An affine transformation.
+ * @matrix2: Another affine transformation.
+ *
+ * Determines whether @matrix1 and @matrix2 are equal, with
+ * epsilon-tolerance for roundoff errors.
+ *
+ * Return value: TRUE if @matrix1 and @matrix2 are equal.
+ **/
+int
+art_affine_equal (double matrix1[6], double matrix2[6])
+{
+ return (fabs (matrix1[0] - matrix2[0]) < EPSILON &&
+ fabs (matrix1[1] - matrix2[1]) < EPSILON &&
+ fabs (matrix1[2] - matrix2[2]) < EPSILON &&
+ fabs (matrix1[3] - matrix2[3]) < EPSILON &&
+ fabs (matrix1[4] - matrix2[4]) < EPSILON &&
+ fabs (matrix1[5] - matrix2[5]) < EPSILON);
+}
diff -Nru swftools-0.9.2+ds1/lib/art/art_affine.h swftools-0.9.1/lib/art/art_affine.h
--- swftools-0.9.2+ds1/lib/art/art_affine.h 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/art/art_affine.h 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,93 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __ART_AFFINE_H__
+#define __ART_AFFINE_H__
+
+#ifdef LIBART_COMPILATION
+#include "art_point.h"
+#else
+#include "art_point.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+void
+art_affine_point (ArtPoint *dst, const ArtPoint *src,
+ const double affine[6]);
+
+void
+art_affine_invert (double dst_affine[6], const double src_affine[6]);
+
+/* flip the matrix, FALSE, FALSE is a simple copy operation, and
+ TRUE, TRUE equals a rotation by 180 degrees */
+void
+art_affine_flip (double dst_affine[6], const double src_affine[6],
+ int horz, int vert);
+
+void
+art_affine_to_string (char str[128], const double src[6]);
+
+void
+art_affine_multiply (double dst[6],
+ const double src1[6], const double src2[6]);
+
+/* set up the identity matrix */
+void
+art_affine_identity (double dst[6]);
+
+/* set up a scaling matrix */
+void
+art_affine_scale (double dst[6], double sx, double sy);
+
+/* set up a rotation matrix; theta is given in degrees */
+void
+art_affine_rotate (double dst[6], double theta);
+
+/* set up a shearing matrix; theta is given in degrees */
+void
+art_affine_shear (double dst[6], double theta);
+
+/* set up a translation matrix */
+void
+art_affine_translate (double dst[6], double tx, double ty);
+
+
+/* find the affine's "expansion factor", i.e. the scale amount */
+double
+art_affine_expansion (const double src[6]);
+
+/* Determine whether the affine transformation is rectilinear,
+ i.e. whether a rectangle aligned to the grid is transformed into
+ another rectangle aligned to the grid. */
+int
+art_affine_rectilinear (const double src[6]);
+
+/* Determine whether two affine transformations are equal within grid allignment */
+int
+art_affine_equal (double matrix1[6], double matrix2[6]);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __ART_AFFINE_H__ */
diff -Nru swftools-0.9.2+ds1/lib/art/art_alphagamma.c swftools-0.9.1/lib/art/art_alphagamma.c
--- swftools-0.9.2+ds1/lib/art/art_alphagamma.c 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/art/art_alphagamma.c 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,85 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/* Some functions to build alphagamma tables */
+
+#include "config.h"
+#include "art_alphagamma.h"
+
+#include
+
+/**
+ * art_alphagamma_new: Create a new #ArtAlphaGamma.
+ * @gamma: Gamma value.
+ *
+ * Create a new #ArtAlphaGamma for a specific value of @gamma. When
+ * correctly implemented (which is generally not the case in libart),
+ * alpha compositing with an alphagamma parameter is equivalent to
+ * applying the gamma transformation to source images, doing the alpha
+ * compositing (in linear intensity space), then applying the inverse
+ * gamma transformation, bringing it back to a gamma-adjusted
+ * intensity space.
+ *
+ * Return value: The newly created #ArtAlphaGamma.
+ **/
+ArtAlphaGamma *
+art_alphagamma_new (double gamma)
+{
+ int tablesize;
+ ArtAlphaGamma *alphagamma;
+ int i;
+ int *table;
+ art_u8 *invtable;
+ double s, r_gamma;
+
+ tablesize = ceil (gamma * 8);
+ if (tablesize < 10)
+ tablesize = 10;
+
+ alphagamma = (ArtAlphaGamma *)art_alloc (sizeof(ArtAlphaGamma) +
+ ((1 << tablesize) - 1) *
+ sizeof(art_u8));
+ alphagamma->gamma = gamma;
+ alphagamma->invtable_size = tablesize;
+
+ table = alphagamma->table;
+ for (i = 0; i < 256; i++)
+ table[i] = (int)floor (((1 << tablesize) - 1) *
+ pow (i * (1.0 / 255), gamma) + 0.5);
+
+ invtable = alphagamma->invtable;
+ s = 1.0 / ((1 << tablesize) - 1);
+ r_gamma = 1.0 / gamma;
+ for (i = 0; i < 1 << tablesize; i++)
+ invtable[i] = (int)floor (255 * pow (i * s, r_gamma) + 0.5);
+
+ return alphagamma;
+}
+
+/**
+ * art_alphagamma_free: Free an #ArtAlphaGamma.
+ * @alphagamma: An #ArtAlphaGamma.
+ *
+ * Frees the #ArtAlphaGamma.
+ **/
+void
+art_alphagamma_free (ArtAlphaGamma *alphagamma)
+{
+ art_free (alphagamma);
+}
diff -Nru swftools-0.9.2+ds1/lib/art/art_alphagamma.h swftools-0.9.1/lib/art/art_alphagamma.h
--- swftools-0.9.2+ds1/lib/art/art_alphagamma.h 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/art/art_alphagamma.h 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,55 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __ART_ALPHAGAMMA_H__
+#define __ART_ALPHAGAMMA_H__
+
+/* Alphagamma tables */
+
+#ifdef LIBART_COMPILATION
+#include "art_misc.h"
+#else
+#include "art_misc.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+typedef struct _ArtAlphaGamma ArtAlphaGamma;
+
+struct _ArtAlphaGamma {
+ /*< private >*/
+ double gamma;
+ int invtable_size;
+ int table[256];
+ art_u8 invtable[1];
+};
+
+ArtAlphaGamma *
+art_alphagamma_new (double gamma);
+
+void
+art_alphagamma_free (ArtAlphaGamma *alphagamma);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __ART_SVP_H__ */
diff -Nru swftools-0.9.2+ds1/lib/art/art_bpath.c swftools-0.9.1/lib/art/art_bpath.c
--- swftools-0.9.2+ds1/lib/art/art_bpath.c 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/art/art_bpath.c 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,92 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/* Basic constructors and operations for bezier paths */
+
+#include "config.h"
+#include "art_bpath.h"
+
+#include
+
+
+/**
+ * art_bpath_affine_transform: Affine transform an #ArtBpath.
+ * @src: The source #ArtBpath.
+ * @matrix: The affine transform.
+ *
+ * Affine transform the bezpath, returning a newly allocated #ArtBpath
+ * (allocated using art_alloc()).
+ *
+ * Result (x', y') = (matrix[0] * x + matrix[2] * y + matrix[4],
+ * matrix[1] * x + matrix[3] * y + matrix[5])
+ *
+ * Return value: the transformed #ArtBpath.
+ **/
+ArtBpath *
+art_bpath_affine_transform (const ArtBpath *src, const double matrix[6])
+{
+ int i;
+ int size;
+ ArtBpath *xnew;
+ ArtPathcode code;
+ double x, y;
+
+ for (i = 0; src[i].code != ART_END; i++);
+ size = i;
+
+ xnew = art_new (ArtBpath, size + 1);
+
+ for (i = 0; i < size; i++)
+ {
+ code = src[i].code;
+ xnew[i].code = code;
+ if (code == ART_CURVETO)
+ {
+ x = src[i].x1;
+ y = src[i].y1;
+ xnew[i].x1 = matrix[0] * x + matrix[2] * y + matrix[4];
+ xnew[i].y1 = matrix[1] * x + matrix[3] * y + matrix[5];
+ x = src[i].x2;
+ y = src[i].y2;
+ xnew[i].x2 = matrix[0] * x + matrix[2] * y + matrix[4];
+ xnew[i].y2 = matrix[1] * x + matrix[3] * y + matrix[5];
+ }
+ else
+ {
+ xnew[i].x1 = 0;
+ xnew[i].y1 = 0;
+ xnew[i].x2 = 0;
+ xnew[i].y2 = 0;
+ }
+ x = src[i].x3;
+ y = src[i].y3;
+ xnew[i].x3 = matrix[0] * x + matrix[2] * y + matrix[4];
+ xnew[i].y3 = matrix[1] * x + matrix[3] * y + matrix[5];
+ }
+ xnew[i].code = ART_END;
+ xnew[i].x1 = 0;
+ xnew[i].y1 = 0;
+ xnew[i].x2 = 0;
+ xnew[i].y2 = 0;
+ xnew[i].x3 = 0;
+ xnew[i].y3 = 0;
+
+ return xnew;
+}
+
diff -Nru swftools-0.9.2+ds1/lib/art/art_bpath.h swftools-0.9.1/lib/art/art_bpath.h
--- swftools-0.9.2+ds1/lib/art/art_bpath.h 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/art/art_bpath.h 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,59 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __ART_BPATH_H__
+#define __ART_BPATH_H__
+
+#ifdef LIBART_COMPILATION
+#include "art_misc.h"
+#include "art_point.h"
+#include "art_pathcode.h"
+#else
+#include "art_misc.h"
+#include "art_point.h"
+#include "art_pathcode.h"
+#endif
+
+/* Basic data structures and constructors for bezier paths */
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+typedef struct _ArtBpath ArtBpath;
+
+struct _ArtBpath {
+ /*< public >*/
+ ArtPathcode code;
+ double x1;
+ double y1;
+ double x2;
+ double y2;
+ double x3;
+ double y3;
+};
+
+ArtBpath *
+art_bpath_affine_transform (const ArtBpath *src, const double matrix[6]);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __ART_BPATH_H__ */
diff -Nru swftools-0.9.2+ds1/lib/art/art_config.h swftools-0.9.1/lib/art/art_config.h
--- swftools-0.9.2+ds1/lib/art/art_config.h 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/art/art_config.h 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,10 @@
+/* Automatically generated by gen_art_config.c */
+
+#define ART_SIZEOF_CHAR 1
+#define ART_SIZEOF_SHORT 2
+#define ART_SIZEOF_INT 4
+#define ART_SIZEOF_LONG 4
+
+typedef unsigned char art_u8;
+typedef unsigned short art_u16;
+typedef unsigned int art_u32;
diff -Nru swftools-0.9.2+ds1/lib/art/art_filterlevel.h swftools-0.9.1/lib/art/art_filterlevel.h
--- swftools-0.9.2+ds1/lib/art/art_filterlevel.h 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/art/art_filterlevel.h 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,68 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __ART_FILTERLEVEL_H__
+#define __ART_FILTERLEVEL_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+typedef enum {
+ ART_FILTER_NEAREST,
+ ART_FILTER_TILES,
+ ART_FILTER_BILINEAR,
+ ART_FILTER_HYPER
+} ArtFilterLevel;
+
+/* NEAREST is nearest neighbor. It is the fastest and lowest quality.
+
+ TILES is an accurate simulation of the PostScript image operator
+ without any interpolation enabled; each pixel is rendered as a tiny
+ parallelogram of solid color, the edges of which are implemented
+ with antialiasing. It resembles nearest neighbor for enlargement,
+ and bilinear for reduction.
+
+ BILINEAR is bilinear interpolation. For enlargement, it is
+ equivalent to point-sampling the ideal bilinear-interpolated
+ image. For reduction, it is equivalent to laying down small tiles
+ and integrating over the coverage area.
+
+ HYPER is the highest quality reconstruction function. It is derived
+ from the hyperbolic filters in Wolberg's "Digital Image Warping,"
+ and is formally defined as the hyperbolic-filter sampling the ideal
+ hyperbolic-filter interpolated image (the filter is designed to be
+ idempotent for 1:1 pixel mapping). It is the slowest and highest
+ quality.
+
+ Note: at this stage of implementation, most filter modes are likely
+ not to be implemented.
+
+ Note: cubic filtering is missing from this list, because there isn't
+ much point - hyper is just as fast to implement and slightly better
+ in quality.
+
+*/
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __ART_PATHCODE_H__ */
diff -Nru swftools-0.9.2+ds1/lib/art/art_gray_svp.c swftools-0.9.1/lib/art/art_gray_svp.c
--- swftools-0.9.2+ds1/lib/art/art_gray_svp.c 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/art/art_gray_svp.c 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,123 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/* Render a sorted vector path into a graymap. */
+
+#include "config.h"
+#include "art_gray_svp.h"
+
+#include /* for memset */
+#include "art_misc.h"
+
+#include "art_svp.h"
+#include "art_svp_render_aa.h"
+
+typedef struct _ArtGraySVPData ArtGraySVPData;
+
+struct _ArtGraySVPData {
+ art_u8 *buf;
+ int rowstride;
+ int x0, x1;
+};
+
+static void
+art_gray_svp_callback (void *callback_data, int y,
+ int start, ArtSVPRenderAAStep *steps, int n_steps)
+{
+ ArtGraySVPData *data = (ArtGraySVPData *)callback_data;
+ art_u8 *linebuf;
+ int run_x0, run_x1;
+ int running_sum = start;
+ int x0, x1;
+ int k;
+
+#if 0
+ printf ("start = %d", start);
+ running_sum = start;
+ for (k = 0; k < n_steps; k++)
+ {
+ running_sum += steps[k].delta;
+ printf (" %d:%d", steps[k].x, running_sum >> 16);
+ }
+ printf ("\n");
+#endif
+
+ linebuf = data->buf;
+ x0 = data->x0;
+ x1 = data->x1;
+
+ if (n_steps > 0)
+ {
+ run_x1 = steps[0].x;
+ if (run_x1 > x0)
+ memset (linebuf, running_sum >> 16, run_x1 - x0);
+
+ for (k = 0; k < n_steps - 1; k++)
+ {
+ running_sum += steps[k].delta;
+ run_x0 = run_x1;
+ run_x1 = steps[k + 1].x;
+ if (run_x1 > run_x0)
+ memset (linebuf + run_x0 - x0, running_sum >> 16, run_x1 - run_x0);
+ }
+ running_sum += steps[k].delta;
+ if (x1 > run_x1)
+ memset (linebuf + run_x1 - x0, running_sum >> 16, x1 - run_x1);
+ }
+ else
+ {
+ memset (linebuf, running_sum >> 16, x1 - x0);
+ }
+
+ data->buf += data->rowstride;
+}
+
+/**
+ * art_gray_svp_aa: Render the vector path into the bytemap.
+ * @svp: The SVP to render.
+ * @x0: The view window's left coord.
+ * @y0: The view window's top coord.
+ * @x1: The view window's right coord.
+ * @y1: The view window's bottom coord.
+ * @buf: The buffer where the bytemap is stored.
+ * @rowstride: the rowstride for @buf.
+ *
+ * Each pixel gets a value proportional to the area within the pixel
+ * overlapping the (filled) SVP. Pixel (x, y) is stored at:
+ *
+ * @buf[(y - * @y0) * @rowstride + (x - @x0)]
+ *
+ * All pixels @x0 <= x < @x1, @y0 <= y < @y1 are generated. A
+ * stored value of zero is no coverage, and a value of 255 is full
+ * coverage. The area within the pixel (x, y) is the region covered
+ * by [x..x+1] and [y..y+1].
+ **/
+void
+art_gray_svp_aa (const ArtSVP *svp,
+ int x0, int y0, int x1, int y1,
+ art_u8 *buf, int rowstride)
+{
+ ArtGraySVPData data;
+
+ data.buf = buf;
+ data.rowstride = rowstride;
+ data.x0 = x0;
+ data.x1 = x1;
+ art_svp_render_aa (svp, x0, y0, x1, y1, art_gray_svp_callback, &data);
+}
diff -Nru swftools-0.9.2+ds1/lib/art/art_gray_svp.h swftools-0.9.1/lib/art/art_gray_svp.h
--- swftools-0.9.2+ds1/lib/art/art_gray_svp.h 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/art/art_gray_svp.h 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,46 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/* Render a sorted vector path into a graymap. */
+
+#ifndef __ART_GRAY_SVP_H__
+#define __ART_GRAY_SVP_H__
+
+#ifdef LIBART_COMPILATION
+#include "art_misc.h"
+#include "art_svp.h"
+#else
+#include "art_misc.h"
+#include "art_svp.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+void
+art_gray_svp_aa (const ArtSVP *svp,
+ int x0, int y0, int x1, int y1,
+ art_u8 *buf, int rowstride);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __ART_GRAY_SVP_H__ */
diff -Nru swftools-0.9.2+ds1/lib/art/art_misc.c swftools-0.9.1/lib/art/art_misc.c
--- swftools-0.9.2+ds1/lib/art/art_misc.c 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/art/art_misc.c 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,80 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/* Various utility functions RLL finds useful. */
+
+#include "config.h"
+#include "art_misc.h"
+
+#ifdef HAVE_UINSTD_H
+#include
+#endif
+#include
+#include
+
+/**
+ * art_die: Print the error message to stderr and exit with a return code of 1.
+ * @fmt: The printf-style format for the error message.
+ *
+ * Used for dealing with severe errors.
+ **/
+void
+art_die (const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start (ap, fmt);
+ vfprintf (stderr, fmt, ap);
+ va_end (ap);
+ exit (1);
+}
+
+/**
+ * art_warn: Print the warning message to stderr.
+ * @fmt: The printf-style format for the warning message.
+ *
+ * Used for generating warnings.
+ **/
+void
+art_warn (const char *fmt, ...)
+{
+ va_list ap;
+
+ fprintf(stderr, "warn: ");
+ va_start (ap, fmt);
+ vfprintf (stderr, fmt, ap);
+ va_end (ap);
+}
+
+/**
+ * art_dprint: Print the debug message to stderr.
+ * @fmt: The printf-style format for the debug message.
+ *
+ * Used for generating debug output.
+ **/
+void
+art_dprint (const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start (ap, fmt);
+ vfprintf (stderr, fmt, ap);
+ va_end (ap);
+}
+
diff -Nru swftools-0.9.2+ds1/lib/art/art_misc.h swftools-0.9.1/lib/art/art_misc.h
--- swftools-0.9.2+ds1/lib/art/art_misc.h 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/art/art_misc.h 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,103 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/* Simple macros to set up storage allocation and basic types for libart
+ functions. */
+
+#ifndef __ART_MISC_H__
+#define __ART_MISC_H__
+
+#include /* for malloc, etc. */
+
+/* The art_config.h file is automatically generated by
+ gen_art_config.c and contains definitions of
+ ART_SIZEOF_{CHAR,SHORT,INT,LONG} and art_u{8,16,32}. */
+#ifdef LIBART_COMPILATION
+#include "art_config.h"
+#else
+#include "art_config.h"
+#endif
+
+#include "../mem.h"
+#ifdef __mem_h__
+#define art_alloc rfx_alloc
+#define art_free rfx_free
+#define art_realloc rfx_realloc
+#else
+#define art_alloc malloc
+#define art_free free
+#define art_realloc realloc
+#endif
+
+/* These aren't, strictly speaking, configuration macros, but they're
+ damn handy to have around, and may be worth playing with for
+ debugging. */
+#define art_new(type, n) ((type *)art_alloc ((n) * sizeof(type)))
+
+#define art_renew(p, type, n) ((type *)art_realloc (p, (n) * sizeof(type)))
+
+/* This one must be used carefully - in particular, p and max should
+ be variables. They can also be pstruct->el lvalues. */
+#define art_expand(p, type, max) do { if(max) { p = art_renew (p, type, max <<= 1); } else { max = 1; p = art_new(type, 1); } } while (0)
+
+typedef int art_boolean;
+#define ART_FALSE 0
+#define ART_TRUE 1
+
+/* define pi */
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif /* M_PI */
+
+#ifndef M_SQRT2
+#define M_SQRT2 1.41421356237309504880 /* sqrt(2) */
+#endif /* M_SQRT2 */
+
+/* Provide macros to feature the GCC function attribute.
+ */
+#if defined(__GNUC__) && (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 4))
+#define ART_GNUC_PRINTF( format_idx, arg_idx ) \
+ __attribute__((format (printf, format_idx, arg_idx)))
+#define ART_GNUC_NORETURN \
+ __attribute__((noreturn))
+#else /* !__GNUC__ */
+#define ART_GNUC_PRINTF( format_idx, arg_idx )
+#define ART_GNUC_NORETURN
+#endif /* !__GNUC__ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void ART_GNUC_NORETURN
+art_die (const char *fmt, ...) ART_GNUC_PRINTF (1, 2);
+
+void
+art_warn (const char *fmt, ...) ART_GNUC_PRINTF (1, 2);
+
+void
+art_dprint (const char *fmt, ...) ART_GNUC_PRINTF (1, 2);
+
+#ifdef __cplusplus
+}
+#endif
+
+#define ART_USE_NEW_INTERSECTOR
+
+#endif /* __ART_MISC_H__ */
diff -Nru swftools-0.9.2+ds1/lib/art/art_pathcode.h swftools-0.9.1/lib/art/art_pathcode.h
--- swftools-0.9.2+ds1/lib/art/art_pathcode.h 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/art/art_pathcode.h 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,39 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __ART_PATHCODE_H__
+#define __ART_PATHCODE_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+typedef enum {
+ ART_MOVETO,
+ ART_MOVETO_OPEN,
+ ART_CURVETO,
+ ART_LINETO,
+ ART_END
+} ArtPathcode;
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __ART_PATHCODE_H__ */
diff -Nru swftools-0.9.2+ds1/lib/art/art_pixbuf.c swftools-0.9.1/lib/art/art_pixbuf.c
--- swftools-0.9.2+ds1/lib/art/art_pixbuf.c 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/art/art_pixbuf.c 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,285 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+#include "art_pixbuf.h"
+
+#include "art_misc.h"
+#include
+
+/**
+ * art_pixbuf_new_rgb_dnotify: Create a new RGB #ArtPixBuf with explicit destroy notification.
+ * @pixels: A buffer containing the actual pixel data.
+ * @width: The width of the pixbuf.
+ * @height: The height of the pixbuf.
+ * @rowstride: The rowstride of the pixbuf.
+ * @dfunc_data: The private data passed to @dfunc.
+ * @dfunc: The destroy notification function.
+ *
+ * Creates a generic data structure for holding a buffer of RGB
+ * pixels. It is possible to think of an #ArtPixBuf as a
+ * virtualization over specific pixel buffer formats.
+ *
+ * @dfunc is called with @dfunc_data and @pixels as arguments when the
+ * #ArtPixBuf is destroyed. Using a destroy notification function
+ * allows a wide range of memory management disciplines for the pixel
+ * memory. A NULL value for @dfunc is also allowed and means that no
+ * special action will be taken on destruction.
+ *
+ * Return value: The newly created #ArtPixBuf.
+ **/
+ArtPixBuf *
+art_pixbuf_new_rgb_dnotify (art_u8 *pixels, int width, int height, int rowstride,
+ void *dfunc_data, ArtDestroyNotify dfunc)
+{
+ ArtPixBuf *pixbuf;
+
+ pixbuf = art_new (ArtPixBuf, 1);
+
+ pixbuf->format = ART_PIX_RGB;
+ pixbuf->n_channels = 3;
+ pixbuf->has_alpha = 0;
+ pixbuf->bits_per_sample = 8;
+
+ pixbuf->pixels = (art_u8 *) pixels;
+ pixbuf->width = width;
+ pixbuf->height = height;
+ pixbuf->rowstride = rowstride;
+ pixbuf->destroy_data = dfunc_data;
+ pixbuf->destroy = dfunc;
+
+ return pixbuf;
+}
+
+/**
+ * art_pixbuf_new_rgba_dnotify: Create a new RGBA #ArtPixBuf with explicit destroy notification.
+ * @pixels: A buffer containing the actual pixel data.
+ * @width: The width of the pixbuf.
+ * @height: The height of the pixbuf.
+ * @rowstride: The rowstride of the pixbuf.
+ * @dfunc_data: The private data passed to @dfunc.
+ * @dfunc: The destroy notification function.
+ *
+ * Creates a generic data structure for holding a buffer of RGBA
+ * pixels. It is possible to think of an #ArtPixBuf as a
+ * virtualization over specific pixel buffer formats.
+ *
+ * @dfunc is called with @dfunc_data and @pixels as arguments when the
+ * #ArtPixBuf is destroyed. Using a destroy notification function
+ * allows a wide range of memory management disciplines for the pixel
+ * memory. A NULL value for @dfunc is also allowed and means that no
+ * special action will be taken on destruction.
+ *
+ * Return value: The newly created #ArtPixBuf.
+ **/
+ArtPixBuf *
+art_pixbuf_new_rgba_dnotify (art_u8 *pixels, int width, int height, int rowstride,
+ void *dfunc_data, ArtDestroyNotify dfunc)
+{
+ ArtPixBuf *pixbuf;
+
+ pixbuf = art_new (ArtPixBuf, 1);
+
+ pixbuf->format = ART_PIX_RGB;
+ pixbuf->n_channels = 4;
+ pixbuf->has_alpha = 1;
+ pixbuf->bits_per_sample = 8;
+
+ pixbuf->pixels = (art_u8 *) pixels;
+ pixbuf->width = width;
+ pixbuf->height = height;
+ pixbuf->rowstride = rowstride;
+ pixbuf->destroy_data = dfunc_data;
+ pixbuf->destroy = dfunc;
+
+ return pixbuf;
+}
+
+/**
+ * art_pixbuf_new_const_rgb: Create a new RGB #ArtPixBuf with constant pixel data.
+ * @pixels: A buffer containing the actual pixel data.
+ * @width: The width of the pixbuf.
+ * @height: The height of the pixbuf.
+ * @rowstride: The rowstride of the pixbuf.
+ *
+ * Creates a generic data structure for holding a buffer of RGB
+ * pixels. It is possible to think of an #ArtPixBuf as a
+ * virtualization over specific pixel buffer formats.
+ *
+ * No action is taken when the #ArtPixBuf is destroyed. Thus, this
+ * function is useful when the pixel data is constant or statically
+ * allocated.
+ *
+ * Return value: The newly created #ArtPixBuf.
+ **/
+ArtPixBuf *
+art_pixbuf_new_const_rgb (const art_u8 *pixels, int width, int height, int rowstride)
+{
+ return art_pixbuf_new_rgb_dnotify ((art_u8 *) pixels, width, height, rowstride, NULL, NULL);
+}
+
+/**
+ * art_pixbuf_new_const_rgba: Create a new RGBA #ArtPixBuf with constant pixel data.
+ * @pixels: A buffer containing the actual pixel data.
+ * @width: The width of the pixbuf.
+ * @height: The height of the pixbuf.
+ * @rowstride: The rowstride of the pixbuf.
+ *
+ * Creates a generic data structure for holding a buffer of RGBA
+ * pixels. It is possible to think of an #ArtPixBuf as a
+ * virtualization over specific pixel buffer formats.
+ *
+ * No action is taken when the #ArtPixBuf is destroyed. Thus, this
+ * function is suitable when the pixel data is constant or statically
+ * allocated.
+ *
+ * Return value: The newly created #ArtPixBuf.
+ **/
+ArtPixBuf *
+art_pixbuf_new_const_rgba (const art_u8 *pixels, int width, int height, int rowstride)
+{
+ return art_pixbuf_new_rgba_dnotify ((art_u8 *) pixels, width, height, rowstride, NULL, NULL);
+}
+
+static void
+art_pixel_destroy (void *func_data, void *data)
+{
+ art_free (data);
+}
+
+/**
+ * art_pixbuf_new_rgb: Create a new RGB #ArtPixBuf.
+ * @pixels: A buffer containing the actual pixel data.
+ * @width: The width of the pixbuf.
+ * @height: The height of the pixbuf.
+ * @rowstride: The rowstride of the pixbuf.
+ *
+ * Creates a generic data structure for holding a buffer of RGB
+ * pixels. It is possible to think of an #ArtPixBuf as a
+ * virtualization over specific pixel buffer formats.
+ *
+ * The @pixels buffer is freed with art_free() when the #ArtPixBuf is
+ * destroyed. Thus, this function is suitable when the pixel data is
+ * allocated with art_alloc().
+ *
+ * Return value: The newly created #ArtPixBuf.
+ **/
+ArtPixBuf *
+art_pixbuf_new_rgb (art_u8 *pixels, int width, int height, int rowstride)
+{
+ return art_pixbuf_new_rgb_dnotify (pixels, width, height, rowstride, NULL, art_pixel_destroy);
+}
+
+/**
+ * art_pixbuf_new_rgba: Create a new RGBA #ArtPixBuf.
+ * @pixels: A buffer containing the actual pixel data.
+ * @width: The width of the pixbuf.
+ * @height: The height of the pixbuf.
+ * @rowstride: The rowstride of the pixbuf.
+ *
+ * Creates a generic data structure for holding a buffer of RGBA
+ * pixels. It is possible to think of an #ArtPixBuf as a
+ * virtualization over specific pixel buffer formats.
+ *
+ * The @pixels buffer is freed with art_free() when the #ArtPixBuf is
+ * destroyed. Thus, this function is suitable when the pixel data is
+ * allocated with art_alloc().
+ *
+ * Return value: The newly created #ArtPixBuf.
+ **/
+ArtPixBuf *
+art_pixbuf_new_rgba (art_u8 *pixels, int width, int height, int rowstride)
+{
+ return art_pixbuf_new_rgba_dnotify (pixels, width, height, rowstride, NULL, art_pixel_destroy);
+}
+
+/**
+ * art_pixbuf_free: Destroy an #ArtPixBuf.
+ * @pixbuf: The #ArtPixBuf to be destroyed.
+ *
+ * Destroys the #ArtPixBuf, calling the destroy notification function
+ * (if non-NULL) so that the memory for the pixel buffer can be
+ * properly reclaimed.
+ **/
+void
+art_pixbuf_free (ArtPixBuf *pixbuf)
+{
+ ArtDestroyNotify destroy = pixbuf->destroy;
+ void *destroy_data = pixbuf->destroy_data;
+ art_u8 *pixels = pixbuf->pixels;
+
+ pixbuf->pixels = NULL;
+ pixbuf->destroy = NULL;
+ pixbuf->destroy_data = NULL;
+
+ if (destroy)
+ destroy (destroy_data, pixels);
+
+ art_free (pixbuf);
+}
+
+/**
+ * art_pixbuf_free_shallow:
+ * @pixbuf: The #ArtPixBuf to be destroyed.
+ *
+ * Destroys the #ArtPixBuf without calling the destroy notification function.
+ *
+ * This function is deprecated. Use the _dnotify variants for
+ * allocation instead.
+ **/
+void
+art_pixbuf_free_shallow (ArtPixBuf *pixbuf)
+{
+ art_free (pixbuf);
+}
+
+/**
+ * art_pixbuf_duplicate: Duplicate a pixbuf.
+ * @pixbuf: The #ArtPixBuf to duplicate.
+ *
+ * Duplicates a pixbuf, including duplicating the buffer.
+ *
+ * Return value: The duplicated pixbuf.
+ **/
+ArtPixBuf *
+art_pixbuf_duplicate (const ArtPixBuf *pixbuf)
+{
+ ArtPixBuf *result;
+ int size;
+
+ result = art_new (ArtPixBuf, 1);
+
+ result->format = pixbuf->format;
+ result->n_channels = pixbuf->n_channels;
+ result->has_alpha = pixbuf->has_alpha;
+ result->bits_per_sample = pixbuf->bits_per_sample;
+
+ size = (pixbuf->height - 1) * pixbuf->rowstride +
+ pixbuf->width * ((pixbuf->n_channels * pixbuf->bits_per_sample + 7) >> 3);
+ result->pixels = (art_u8*)art_alloc (size);
+ memcpy (result->pixels, pixbuf->pixels, size);
+
+ result->width = pixbuf->width;
+ result->height = pixbuf->height;
+ result->rowstride = pixbuf->rowstride;
+ result->destroy_data = NULL;
+ result->destroy = art_pixel_destroy;
+
+ return result;
+}
diff -Nru swftools-0.9.2+ds1/lib/art/art_pixbuf.h swftools-0.9.1/lib/art/art_pixbuf.h
--- swftools-0.9.2+ds1/lib/art/art_pixbuf.h 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/art/art_pixbuf.h 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,104 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __ART_PIXBUF_H__
+#define __ART_PIXBUF_H__
+
+/* A generic data structure for holding a buffer of pixels. One way
+ to think about this module is as a virtualization over specific
+ pixel buffer formats. */
+
+#ifdef LIBART_COMPILATION
+#include "art_misc.h"
+#else
+#include "art_misc.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+typedef void (*ArtDestroyNotify) (void *func_data, void *data);
+
+typedef struct _ArtPixBuf ArtPixBuf;
+
+typedef enum {
+ ART_PIX_RGB
+ /* gray, cmyk, lab, ... ? */
+} ArtPixFormat;
+
+
+/* The pixel buffer consists of width * height pixels, each of which
+ has n_channels samples. It is stored in simple packed format. */
+
+struct _ArtPixBuf {
+ /*< public >*/
+ ArtPixFormat format;
+ int n_channels;
+ int has_alpha;
+ int bits_per_sample;
+
+ art_u8 *pixels;
+ int width;
+ int height;
+ int rowstride;
+ void *destroy_data;
+ ArtDestroyNotify destroy;
+};
+
+/* allocate an ArtPixBuf from art_alloc()ed pixels (automated destruction) */
+ArtPixBuf *
+art_pixbuf_new_rgb (art_u8 *pixels, int width, int height, int rowstride);
+
+ArtPixBuf *
+art_pixbuf_new_rgba (art_u8 *pixels, int width, int height, int rowstride);
+
+/* allocate an ArtPixBuf from constant pixels (no destruction) */
+ArtPixBuf *
+art_pixbuf_new_const_rgb (const art_u8 *pixels, int width, int height, int rowstride);
+
+ArtPixBuf *
+art_pixbuf_new_const_rgba (const art_u8 *pixels, int width, int height, int rowstride);
+
+/* allocate an ArtPixBuf and notify creator upon destruction */
+ArtPixBuf *
+art_pixbuf_new_rgb_dnotify (art_u8 *pixels, int width, int height, int rowstride,
+ void *dfunc_data, ArtDestroyNotify dfunc);
+
+ArtPixBuf *
+art_pixbuf_new_rgba_dnotify (art_u8 *pixels, int width, int height, int rowstride,
+ void *dfunc_data, ArtDestroyNotify dfunc);
+
+/* free an ArtPixBuf with destroy notification */
+void
+art_pixbuf_free (ArtPixBuf *pixbuf);
+
+/* deprecated function, use the _dnotify variants for allocation instead */
+void
+art_pixbuf_free_shallow (ArtPixBuf *pixbuf);
+
+ArtPixBuf *
+art_pixbuf_duplicate (const ArtPixBuf *pixbuf);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff -Nru swftools-0.9.2+ds1/lib/art/art_point.h swftools-0.9.1/lib/art/art_point.h
--- swftools-0.9.2+ds1/lib/art/art_point.h 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/art/art_point.h 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,38 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __ART_POINT_H__
+#define __ART_POINT_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+typedef struct _ArtPoint ArtPoint;
+
+struct _ArtPoint {
+ /*< public >*/
+ double x, y;
+};
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __ART_POINT_H__ */
diff -Nru swftools-0.9.2+ds1/lib/art/art_rect.c swftools-0.9.1/lib/art/art_rect.c
--- swftools-0.9.2+ds1/lib/art/art_rect.c 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/art/art_rect.c 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,215 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+#include "art_rect.h"
+
+#include
+
+#ifndef MAX
+#define MAX(a, b) (((a) > (b)) ? (a) : (b))
+#endif /* MAX */
+
+#ifndef MIN
+#define MIN(a, b) (((a) < (b)) ? (a) : (b))
+#endif /* MIN */
+
+/* rectangle primitives stolen from gzilla */
+
+/**
+ * art_irect_copy: Make a copy of an integer rectangle.
+ * @dest: Where the copy is stored.
+ * @src: The source rectangle.
+ *
+ * Copies the rectangle.
+ **/
+void
+art_irect_copy (ArtIRect *dest, const ArtIRect *src) {
+ dest->x0 = src->x0;
+ dest->y0 = src->y0;
+ dest->x1 = src->x1;
+ dest->y1 = src->y1;
+}
+
+/**
+ * art_irect_union: Find union of two integer rectangles.
+ * @dest: Where the result is stored.
+ * @src1: A source rectangle.
+ * @src2: Another source rectangle.
+ *
+ * Finds the smallest rectangle that includes @src1 and @src2.
+ **/
+void
+art_irect_union (ArtIRect *dest, const ArtIRect *src1, const ArtIRect *src2) {
+ if (art_irect_empty (src1)) {
+ art_irect_copy (dest, src2);
+ } else if (art_irect_empty (src2)) {
+ art_irect_copy (dest, src1);
+ } else {
+ dest->x0 = MIN (src1->x0, src2->x0);
+ dest->y0 = MIN (src1->y0, src2->y0);
+ dest->x1 = MAX (src1->x1, src2->x1);
+ dest->y1 = MAX (src1->y1, src2->y1);
+ }
+}
+
+/**
+ * art_irect_intersection: Find intersection of two integer rectangles.
+ * @dest: Where the result is stored.
+ * @src1: A source rectangle.
+ * @src2: Another source rectangle.
+ *
+ * Finds the intersection of @src1 and @src2.
+ **/
+void
+art_irect_intersect (ArtIRect *dest, const ArtIRect *src1, const ArtIRect *src2) {
+ dest->x0 = MAX (src1->x0, src2->x0);
+ dest->y0 = MAX (src1->y0, src2->y0);
+ dest->x1 = MIN (src1->x1, src2->x1);
+ dest->y1 = MIN (src1->y1, src2->y1);
+}
+
+/**
+ * art_irect_empty: Determine whether integer rectangle is empty.
+ * @src: The source rectangle.
+ *
+ * Return value: TRUE if @src is an empty rectangle, FALSE otherwise.
+ **/
+int
+art_irect_empty (const ArtIRect *src) {
+ return (src->x1 <= src->x0 || src->y1 <= src->y0);
+}
+
+#if 0
+gboolean irect_point_inside (ArtIRect *rect, GzwPoint *point) {
+ return (point->x >= rect->x0 && point->y >= rect->y0 &&
+ point->x < rect->x1 && point->y < rect->y1);
+}
+#endif
+
+/**
+ * art_drect_copy: Make a copy of a rectangle.
+ * @dest: Where the copy is stored.
+ * @src: The source rectangle.
+ *
+ * Copies the rectangle.
+ **/
+void
+art_drect_copy (ArtDRect *dest, const ArtDRect *src) {
+ dest->x0 = src->x0;
+ dest->y0 = src->y0;
+ dest->x1 = src->x1;
+ dest->y1 = src->y1;
+}
+
+/**
+ * art_drect_union: Find union of two rectangles.
+ * @dest: Where the result is stored.
+ * @src1: A source rectangle.
+ * @src2: Another source rectangle.
+ *
+ * Finds the smallest rectangle that includes @src1 and @src2.
+ **/
+void
+art_drect_union (ArtDRect *dest, const ArtDRect *src1, const ArtDRect *src2) {
+ if (art_drect_empty (src1)) {
+ art_drect_copy (dest, src2);
+ } else if (art_drect_empty (src2)) {
+ art_drect_copy (dest, src1);
+ } else {
+ dest->x0 = MIN (src1->x0, src2->x0);
+ dest->y0 = MIN (src1->y0, src2->y0);
+ dest->x1 = MAX (src1->x1, src2->x1);
+ dest->y1 = MAX (src1->y1, src2->y1);
+ }
+}
+
+/**
+ * art_drect_intersection: Find intersection of two rectangles.
+ * @dest: Where the result is stored.
+ * @src1: A source rectangle.
+ * @src2: Another source rectangle.
+ *
+ * Finds the intersection of @src1 and @src2.
+ **/
+void
+art_drect_intersect (ArtDRect *dest, const ArtDRect *src1, const ArtDRect *src2) {
+ dest->x0 = MAX (src1->x0, src2->x0);
+ dest->y0 = MAX (src1->y0, src2->y0);
+ dest->x1 = MIN (src1->x1, src2->x1);
+ dest->y1 = MIN (src1->y1, src2->y1);
+}
+
+/**
+ * art_irect_empty: Determine whether rectangle is empty.
+ * @src: The source rectangle.
+ *
+ * Return value: TRUE if @src is an empty rectangle, FALSE otherwise.
+ **/
+int
+art_drect_empty (const ArtDRect *src) {
+ return (src->x1 <= src->x0 || src->y1 <= src->y0);
+}
+
+/**
+ * art_drect_affine_transform: Affine transform rectangle.
+ * @dst: Where to store the result.
+ * @src: The source rectangle.
+ * @matrix: The affine transformation.
+ *
+ * Find the smallest rectangle enclosing the affine transformed @src.
+ * The result is exactly the affine transformation of @src when
+ * @matrix specifies a rectilinear affine transformation, otherwise it
+ * is a conservative approximation.
+ **/
+void
+art_drect_affine_transform (ArtDRect *dst, const ArtDRect *src, const double matrix[6])
+{
+ double x00, y00, x10, y10;
+ double x01, y01, x11, y11;
+
+ x00 = src->x0 * matrix[0] + src->y0 * matrix[2] + matrix[4];
+ y00 = src->x0 * matrix[1] + src->y0 * matrix[3] + matrix[5];
+ x10 = src->x1 * matrix[0] + src->y0 * matrix[2] + matrix[4];
+ y10 = src->x1 * matrix[1] + src->y0 * matrix[3] + matrix[5];
+ x01 = src->x0 * matrix[0] + src->y1 * matrix[2] + matrix[4];
+ y01 = src->x0 * matrix[1] + src->y1 * matrix[3] + matrix[5];
+ x11 = src->x1 * matrix[0] + src->y1 * matrix[2] + matrix[4];
+ y11 = src->x1 * matrix[1] + src->y1 * matrix[3] + matrix[5];
+ dst->x0 = MIN (MIN (x00, x10), MIN (x01, x11));
+ dst->y0 = MIN (MIN (y00, y10), MIN (y01, y11));
+ dst->x1 = MAX (MAX (x00, x10), MAX (x01, x11));
+ dst->y1 = MAX (MAX (y00, y10), MAX (y01, y11));
+}
+
+/**
+ * art_drect_to_irect: Convert rectangle to integer rectangle.
+ * @dst: Where to store resulting integer rectangle.
+ * @src: The source rectangle.
+ *
+ * Find the smallest integer rectangle that encloses @src.
+ **/
+void
+art_drect_to_irect (ArtIRect *dst, ArtDRect *src)
+{
+ dst->x0 = floor (src->x0);
+ dst->y0 = floor (src->y0);
+ dst->x1 = ceil (src->x1);
+ dst->y1 = ceil (src->y1);
+}
diff -Nru swftools-0.9.2+ds1/lib/art/art_rect.h swftools-0.9.1/lib/art/art_rect.h
--- swftools-0.9.2+ds1/lib/art/art_rect.h 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/art/art_rect.h 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,78 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __ART_RECT_H__
+#define __ART_RECT_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct _ArtDRect ArtDRect;
+typedef struct _ArtIRect ArtIRect;
+
+struct _ArtDRect {
+ /*< public >*/
+ double x0, y0, x1, y1;
+};
+
+struct _ArtIRect {
+ /*< public >*/
+ int x0, y0, x1, y1;
+};
+
+/* Make a copy of the rectangle. */
+void art_irect_copy (ArtIRect *dest, const ArtIRect *src);
+
+/* Find the smallest rectangle that includes both source rectangles. */
+void art_irect_union (ArtIRect *dest,
+ const ArtIRect *src1, const ArtIRect *src2);
+
+/* Return the intersection of the two rectangles */
+void art_irect_intersect (ArtIRect *dest,
+ const ArtIRect *src1, const ArtIRect *src2);
+
+/* Return true if the rectangle is empty. */
+int art_irect_empty (const ArtIRect *src);
+
+/* Make a copy of the rectangle. */
+void art_drect_copy (ArtDRect *dest, const ArtDRect *src);
+
+/* Find the smallest rectangle that includes both source rectangles. */
+void art_drect_union (ArtDRect *dest,
+ const ArtDRect *src1, const ArtDRect *src2);
+
+/* Return the intersection of the two rectangles */
+void art_drect_intersect (ArtDRect *dest,
+ const ArtDRect *src1, const ArtDRect *src2);
+
+/* Return true if the rectangle is empty. */
+int art_drect_empty (const ArtDRect *src);
+
+void
+art_drect_affine_transform (ArtDRect *dst, const ArtDRect *src,
+ const double matrix[6]);
+
+void art_drect_to_irect (ArtIRect *dst, ArtDRect *src);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff -Nru swftools-0.9.2+ds1/lib/art/art_rect_svp.c swftools-0.9.1/lib/art/art_rect_svp.c
--- swftools-0.9.2+ds1/lib/art/art_rect_svp.c 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/art/art_rect_svp.c 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,82 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+#include "art_rect_svp.h"
+
+#include "art_misc.h"
+#include "art_svp.h"
+#include "art_rect.h"
+
+#ifndef MAX
+#define MAX(a, b) (((a) > (b)) ? (a) : (b))
+#endif /* MAX */
+
+#ifndef MIN
+#define MIN(a, b) (((a) < (b)) ? (a) : (b))
+#endif /* MIN */
+
+/**
+ * art_drect_svp: Find the bounding box of a sorted vector path.
+ * @bbox: Where to store the bounding box.
+ * @svp: The SVP.
+ *
+ * Finds the bounding box of the SVP.
+ **/
+void
+art_drect_svp (ArtDRect *bbox, const ArtSVP *svp)
+{
+ int i;
+
+ if (svp->n_segs == 0)
+ {
+ bbox->x0 = 0;
+ bbox->y0 = 0;
+ bbox->x1 = 0;
+ bbox->y1 = 0;
+ return;
+ }
+
+ art_drect_copy (bbox, &svp->segs[0].bbox);
+
+ for (i = 1; i < svp->n_segs; i++)
+ {
+ bbox->x0 = MIN (bbox->x0, svp->segs[i].bbox.x0);
+ bbox->y0 = MIN (bbox->y0, svp->segs[i].bbox.y0);
+ bbox->x1 = MAX (bbox->x1, svp->segs[i].bbox.x1);
+ bbox->y1 = MAX (bbox->y1, svp->segs[i].bbox.y1);
+ }
+}
+
+/**
+ * art_drect_svp_union: Compute the bounding box of the svp and union it in to the existing bounding box.
+ * @bbox: Initial boundin box and where to store the bounding box.
+ * @svp: The SVP.
+ *
+ * Finds the bounding box of the SVP, computing its union with an
+ * existing bbox.
+ **/
+void
+art_drect_svp_union (ArtDRect *bbox, const ArtSVP *svp)
+{
+ ArtDRect svp_bbox;
+
+ art_drect_svp (&svp_bbox, svp);
+ art_drect_union (bbox, bbox, &svp_bbox);
+}
diff -Nru swftools-0.9.2+ds1/lib/art/art_rect_svp.h swftools-0.9.1/lib/art/art_rect_svp.h
--- swftools-0.9.2+ds1/lib/art/art_rect_svp.h 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/art/art_rect_svp.h 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,47 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __ART_RECT_SVP_H__
+#define __ART_RECT_SVP_H__
+
+/* Find the bounding box of a sorted vector path. */
+
+#ifdef LIBART_COMPILATION
+#include "art_svp.h"
+#else
+#include "art_svp.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+void
+art_drect_svp (ArtDRect *bbox, const ArtSVP *svp);
+
+/* Compute the bounding box of the svp and union it in to the
+ existing bounding box. */
+void
+art_drect_svp_union (ArtDRect *bbox, const ArtSVP *svp);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __ART_RECT_SVP_H__ */
diff -Nru swftools-0.9.2+ds1/lib/art/art_rect_uta.c swftools-0.9.1/lib/art/art_rect_uta.c
--- swftools-0.9.2+ds1/lib/art/art_rect_uta.c 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/art/art_rect_uta.c 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,134 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+#include "art_rect_uta.h"
+
+/* Functions to decompose a microtile array into a list of rectangles. */
+
+/**
+ * art_rect_list_from_uta: Decompose uta into list of rectangles.
+ * @uta: The source uta.
+ * @max_width: The maximum width of the resulting rectangles.
+ * @max_height: The maximum height of the resulting rectangles.
+ * @p_nrects: Where to store the number of returned rectangles.
+ *
+ * Allocates a new list of rectangles, sets *@p_nrects to the number
+ * in the list. This list should be freed with art_free().
+ *
+ * Each rectangle bounded in size by (@max_width, @max_height).
+ * However, these bounds must be at least the size of one tile.
+ *
+ * This routine provides a precise implementation, i.e. the rectangles
+ * cover exactly the same area as the uta. It is thus appropriate in
+ * cases where the overhead per rectangle is small compared with the
+ * cost of filling in extra pixels.
+ *
+ * Return value: An array containing the resulting rectangles.
+ **/
+ArtIRect *
+art_rect_list_from_uta (ArtUta *uta, int max_width, int max_height,
+ int *p_nrects)
+{
+ ArtIRect *rects;
+ int n_rects, n_rects_max;
+ int x, y;
+ int width, height;
+ int ix;
+ int left_ix;
+ ArtUtaBbox *utiles;
+ ArtUtaBbox bb;
+ int x0, y0, x1, y1;
+ int *glom;
+ int glom_rect;
+
+ n_rects = 0;
+ n_rects_max = 1;
+ rects = art_new (ArtIRect, n_rects_max);
+
+ width = uta->width;
+ height = uta->height;
+ utiles = uta->utiles;
+
+ glom = art_new (int, width * height);
+ for (ix = 0; ix < width * height; ix++)
+ glom[ix] = -1;
+
+ ix = 0;
+ for (y = 0; y < height; y++)
+ for (x = 0; x < width; x++)
+ {
+ bb = utiles[ix];
+ if (bb)
+ {
+ x0 = ((uta->x0 + x) << ART_UTILE_SHIFT) + ART_UTA_BBOX_X0(bb);
+ y0 = ((uta->y0 + y) << ART_UTILE_SHIFT) + ART_UTA_BBOX_Y0(bb);
+ y1 = ((uta->y0 + y) << ART_UTILE_SHIFT) + ART_UTA_BBOX_Y1(bb);
+
+ left_ix = ix;
+ /* now try to extend to the right */
+ while (x != width - 1 &&
+ ART_UTA_BBOX_X1(bb) == ART_UTILE_SIZE &&
+ (((bb & 0xffffff) ^ utiles[ix + 1]) & 0xffff00ff) == 0 &&
+ (((uta->x0 + x + 1) << ART_UTILE_SHIFT) +
+ ART_UTA_BBOX_X1(utiles[ix + 1]) -
+ x0) <= max_width)
+ {
+ bb = utiles[ix + 1];
+ ix++;
+ x++;
+ }
+ x1 = ((uta->x0 + x) << ART_UTILE_SHIFT) + ART_UTA_BBOX_X1(bb);
+
+
+ /* if rectangle nonempty */
+ if ((x1 ^ x0) | (y1 ^ y0))
+ {
+ /* try to glom onto an existing rectangle */
+ glom_rect = glom[left_ix];
+ if (glom_rect != -1 &&
+ x0 == rects[glom_rect].x0 &&
+ x1 == rects[glom_rect].x1 &&
+ y0 == rects[glom_rect].y1 &&
+ y1 - rects[glom_rect].y0 <= max_height)
+ {
+ rects[glom_rect].y1 = y1;
+ }
+ else
+ {
+ if (n_rects == n_rects_max)
+ art_expand (rects, ArtIRect, n_rects_max);
+ rects[n_rects].x0 = x0;
+ rects[n_rects].y0 = y0;
+ rects[n_rects].x1 = x1;
+ rects[n_rects].y1 = y1;
+ glom_rect = n_rects;
+ n_rects++;
+ }
+ if (y != height - 1)
+ glom[left_ix + width] = glom_rect;
+ }
+ }
+ ix++;
+ }
+
+ art_free (glom);
+ *p_nrects = n_rects;
+ return rects;
+}
diff -Nru swftools-0.9.2+ds1/lib/art/art_rect_uta.h swftools-0.9.1/lib/art/art_rect_uta.h
--- swftools-0.9.2+ds1/lib/art/art_rect_uta.h 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/art/art_rect_uta.h 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,43 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __ART_RECT_UTA_H__
+#define __ART_RECT_UTA_H__
+
+#ifdef LIBART_COMPILATION
+#include "art_rect.h"
+#include "art_uta.h"
+#else
+#include "art_rect.h"
+#include "art_uta.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+ArtIRect *
+art_rect_list_from_uta (ArtUta *uta, int max_width, int max_height,
+ int *p_nrects);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __ART_RECT_UTA_H__ */
diff -Nru swftools-0.9.2+ds1/lib/art/art_render.c swftools-0.9.1/lib/art/art_render.c
--- swftools-0.9.2+ds1/lib/art/art_render.c 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/art/art_render.c 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,1383 @@
+/*
+ * art_render.c: Modular rendering architecture.
+ *
+ * Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 2000 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+#include "art_render.h"
+
+#include "art_rgb.h"
+
+typedef struct _ArtRenderPriv ArtRenderPriv;
+
+struct _ArtRenderPriv {
+ ArtRender super;
+
+ ArtImageSource *image_source;
+
+ int n_mask_source;
+ ArtMaskSource **mask_source;
+
+ int n_callbacks;
+ ArtRenderCallback **callbacks;
+};
+
+ArtRender *
+art_render_new (int x0, int y0, int x1, int y1,
+ art_u8 *pixels, int rowstride,
+ int n_chan, int depth, ArtAlphaType alpha_type,
+ ArtAlphaGamma *alphagamma)
+{
+ ArtRenderPriv *priv;
+ ArtRender *result;
+
+ priv = art_new (ArtRenderPriv, 1);
+ result = &priv->super;
+
+ if (n_chan > ART_MAX_CHAN)
+ {
+ art_warn ("art_render_new: n_chan = %d, exceeds %d max\n",
+ n_chan, ART_MAX_CHAN);
+ return NULL;
+ }
+ if (depth > ART_MAX_DEPTH)
+ {
+ art_warn ("art_render_new: depth = %d, exceeds %d max\n",
+ depth, ART_MAX_DEPTH);
+ return NULL;
+ }
+ if (x0 >= x1)
+ {
+ art_warn ("art_render_new: x0 >= x1 (x0 = %d, x1 = %d)\n", x0, x1);
+ return NULL;
+ }
+ result->x0 = x0;
+ result->y0 = y0;
+ result->x1 = x1;
+ result->y1 = y1;
+ result->pixels = pixels;
+ result->rowstride = rowstride;
+ result->n_chan = n_chan;
+ result->depth = depth;
+ result->alpha_type = alpha_type;
+
+ result->clear = ART_FALSE;
+ result->opacity = 0x10000;
+ result->compositing_mode = ART_COMPOSITE_NORMAL;
+ result->alphagamma = alphagamma;
+
+ result->alpha_buf = NULL;
+ result->image_buf = NULL;
+
+ result->run = NULL;
+ result->span_x = NULL;
+
+ result->need_span = ART_FALSE;
+
+ priv->image_source = NULL;
+
+ priv->n_mask_source = 0;
+ priv->mask_source = NULL;
+
+ return result;
+}
+
+/* todo on clear routines: I haven't really figured out what to do
+ with clearing the alpha channel. It _should_ be possible to clear
+ to an arbitrary RGBA color. */
+
+/**
+ * art_render_clear: Set clear color.
+ * @clear_color: Color with which to clear dest.
+ *
+ * Sets clear color, equivalent to actually clearing the destination
+ * buffer before rendering. This is the most general form.
+ **/
+void
+art_render_clear (ArtRender *render, const ArtPixMaxDepth *clear_color)
+{
+ int i;
+ int n_ch = render->n_chan + (render->alpha_type != ART_ALPHA_NONE);
+
+ render->clear = ART_TRUE;
+ for (i = 0; i < n_ch; i++)
+ render->clear_color[i] = clear_color[i];
+}
+
+/**
+ * art_render_clear_rgb: Set clear color, given in RGB format.
+ * @clear_rgb: Clear color, in 0xRRGGBB format.
+ *
+ * Sets clear color, equivalent to actually clearing the destination
+ * buffer before rendering.
+ **/
+void
+art_render_clear_rgb (ArtRender *render, art_u32 clear_rgb)
+{
+ if (render->n_chan != 3)
+ art_warn ("art_render_clear_rgb: called on render with %d channels, only works with 3\n",
+ render->n_chan);
+ else
+ {
+ int r, g, b;
+
+ render->clear = ART_TRUE;
+ r = clear_rgb >> 16;
+ g = (clear_rgb >> 8) & 0xff;
+ b = clear_rgb & 0xff;
+ render->clear_color[0] = ART_PIX_MAX_FROM_8(r);
+ render->clear_color[1] = ART_PIX_MAX_FROM_8(g);
+ render->clear_color[2] = ART_PIX_MAX_FROM_8(b);
+ }
+}
+
+static void
+art_render_nop_done (ArtRenderCallback *self, ArtRender *render)
+{
+}
+
+static void
+art_render_clear_render_rgb8 (ArtRenderCallback *self, ArtRender *render,
+ art_u8 *dest, int y)
+{
+ int width = render->x1 - render->x0;
+ art_u8 r, g, b;
+ ArtPixMaxDepth color_max;
+
+ color_max = render->clear_color[0];
+ r = ART_PIX_8_FROM_MAX (color_max);
+ color_max = render->clear_color[1];
+ g = ART_PIX_8_FROM_MAX (color_max);
+ color_max = render->clear_color[2];
+ b = ART_PIX_8_FROM_MAX (color_max);
+
+ art_rgb_fill_run (dest, r, g, b, width);
+}
+
+static void
+art_render_clear_render_8 (ArtRenderCallback *self, ArtRender *render,
+ art_u8 *dest, int y)
+{
+ int width = render->x1 - render->x0;
+ int i, j;
+ int n_ch = render->n_chan + (render->alpha_type != ART_ALPHA_NONE);
+ int ix;
+ art_u8 color[ART_MAX_CHAN + 1];
+
+ for (j = 0; j < n_ch; j++)
+ {
+ ArtPixMaxDepth color_max = render->clear_color[j];
+ color[j] = ART_PIX_8_FROM_MAX (color_max);
+ }
+
+ ix = 0;
+ for (i = 0; i < width; i++)
+ for (j = 0; j < n_ch; j++)
+ dest[ix++] = color[j];
+}
+
+const ArtRenderCallback art_render_clear_rgb8_obj =
+{
+ art_render_clear_render_rgb8,
+ art_render_nop_done
+};
+
+const ArtRenderCallback art_render_clear_8_obj =
+{
+ art_render_clear_render_8,
+ art_render_nop_done
+};
+
+#if ART_MAX_DEPTH >= 16
+
+static void
+art_render_clear_render_16 (ArtRenderCallback *self, ArtRender *render,
+ art_u8 *dest, int y)
+{
+ int width = render->x1 - render->x0;
+ int i, j;
+ int n_ch = render->n_chan + (render->alpha_type != ART_ALPHA_NONE);
+ int ix;
+ art_u16 *dest_16 = (art_u16 *)dest;
+ art_u8 color[ART_MAX_CHAN + 1];
+
+ for (j = 0; j < n_ch; j++)
+ {
+ int color_16 = render->clear_color[j];
+ color[j] = color_16;
+ }
+
+ ix = 0;
+ for (i = 0; i < width; i++)
+ for (j = 0; j < n_ch; j++)
+ dest_16[ix++] = color[j];
+}
+
+const ArtRenderCallback art_render_clear_16_obj =
+{
+ art_render_clear_render_16,
+ art_render_nop_done
+};
+
+#endif /* ART_MAX_DEPTH >= 16 */
+
+/* todo: inline */
+static ArtRenderCallback *
+art_render_choose_clear_callback (ArtRender *render)
+{
+ ArtRenderCallback *clear_callback;
+
+ if (render->depth == 8)
+ {
+ if (render->n_chan == 3 &&
+ render->alpha_type == ART_ALPHA_NONE)
+ clear_callback = (ArtRenderCallback *)&art_render_clear_rgb8_obj;
+ else
+ clear_callback = (ArtRenderCallback *)&art_render_clear_8_obj;
+ }
+#if ART_MAX_DEPTH >= 16
+ else if (render->depth == 16)
+ clear_callback = (ArtRenderCallback *)&art_render_clear_16_obj;
+#endif
+ else
+ {
+ art_die ("art_render_choose_clear_callback: inconsistent render->depth = %d\n",
+ render->depth);
+ }
+ return clear_callback;
+}
+
+#if 0
+/* todo: get around to writing this */
+static void
+art_render_composite_render_noa_8_norm (ArtRenderCallback *self, ArtRender *render,
+ art_u8 *dest, int y)
+{
+ int width = render->x1 - render->x0;
+
+}
+#endif
+
+/* This is the most general form of the function. It is slow but
+ (hopefully) correct. Actually, I'm still worried about roundoff
+ errors in the premul case - it seems to me that an off-by-one could
+ lead to overflow. */
+static void
+art_render_composite (ArtRenderCallback *self, ArtRender *render,
+ art_u8 *dest, int y)
+{
+ ArtRenderMaskRun *run = render->run;
+ art_u32 depth = render->depth;
+ int n_run = render->n_run;
+ int x0 = render->x0;
+ int x;
+ int run_x0, run_x1;
+ art_u8 *alpha_buf = render->alpha_buf;
+ art_u8 *image_buf = render->image_buf;
+ int i, j;
+ art_u32 tmp;
+ art_u32 run_alpha;
+ art_u32 alpha;
+ int image_ix;
+ art_u16 src[ART_MAX_CHAN + 1];
+ art_u16 dst[ART_MAX_CHAN + 1];
+ int n_chan = render->n_chan;
+ ArtAlphaType alpha_type = render->alpha_type;
+ int n_ch = n_chan + (alpha_type != ART_ALPHA_NONE);
+ int dst_pixstride = n_ch * (depth >> 3);
+ int buf_depth = render->buf_depth;
+ ArtAlphaType buf_alpha = render->buf_alpha;
+ int buf_n_ch = n_chan + (buf_alpha != ART_ALPHA_NONE);
+ int buf_pixstride = buf_n_ch * (buf_depth >> 3);
+ art_u8 *bufptr;
+ art_u32 src_alpha;
+ art_u32 src_mul;
+ art_u8 *dstptr;
+ art_u32 dst_alpha;
+ art_u32 dst_mul;
+
+ image_ix = 0;
+ for (i = 0; i < n_run - 1; i++)
+ {
+ run_x0 = run[i].x;
+ run_x1 = run[i + 1].x;
+ tmp = run[i].alpha;
+ if (tmp < 0x8100)
+ continue;
+
+ run_alpha = (tmp + (tmp >> 8) + (tmp >> 16) - 0x8000) >> 8; /* range [0 .. 0x10000] */
+ bufptr = image_buf + (run_x0 - x0) * buf_pixstride;
+ dstptr = dest + (run_x0 - x0) * dst_pixstride;
+ for (x = run_x0; x < run_x1; x++)
+ {
+ if (alpha_buf)
+ {
+ if (depth == 8)
+ {
+ tmp = run_alpha * alpha_buf[x - x0] + 0x80;
+ /* range 0x80 .. 0xff0080 */
+ alpha = (tmp + (tmp >> 8) + (tmp >> 16)) >> 8;
+ }
+ else /* (depth == 16) */
+ {
+ tmp = ((art_u16 *)alpha_buf)[x - x0];
+ tmp = (run_alpha * tmp + 0x8000) >> 8;
+ /* range 0x80 .. 0xffff80 */
+ alpha = (tmp + (tmp >> 16)) >> 8;
+ }
+ }
+ else
+ alpha = run_alpha;
+ /* alpha is run_alpha * alpha_buf[x], range 0 .. 0x10000 */
+
+ /* convert (src pixel * alpha) to premul alpha form,
+ store in src as 0..0xffff range */
+ if (buf_alpha == ART_ALPHA_NONE)
+ {
+ src_alpha = alpha;
+ src_mul = src_alpha;
+ }
+ else
+ {
+ if (buf_depth == 8)
+ {
+ tmp = alpha * bufptr[n_chan] + 0x80;
+ /* range 0x80 .. 0xff0080 */
+ src_alpha = (tmp + (tmp >> 8) + (tmp >> 16)) >> 8;
+ }
+ else /* (depth == 16) */
+ {
+ tmp = ((art_u16 *)bufptr)[n_chan];
+ tmp = (alpha * tmp + 0x8000) >> 8;
+ /* range 0x80 .. 0xffff80 */
+ src_alpha = (tmp + (tmp >> 16)) >> 8;
+ }
+ if (buf_alpha == ART_ALPHA_SEPARATE)
+ src_mul = src_alpha;
+ else /* buf_alpha == (ART_ALPHA_PREMUL) */
+ src_mul = alpha;
+ }
+ /* src_alpha is the (alpha of the source pixel * alpha),
+ range 0..0x10000 */
+
+ if (buf_depth == 8)
+ {
+ src_mul *= 0x101;
+ for (j = 0; j < n_chan; j++)
+ src[j] = (bufptr[j] * src_mul + 0x8000) >> 16;
+ }
+ else if (buf_depth == 16)
+ {
+ for (j = 0; j < n_chan; j++)
+ src[j] = (((art_u16 *)bufptr)[j] * src_mul + 0x8000) >> 16;
+ }
+ bufptr += buf_pixstride;
+
+ /* src[0..n_chan - 1] (range 0..0xffff) and src_alpha (range
+ 0..0x10000) now contain the source pixel with
+ premultiplied alpha */
+
+ /* convert dst pixel to premul alpha form,
+ store in dst as 0..0xffff range */
+ if (alpha_type == ART_ALPHA_NONE)
+ {
+ dst_alpha = 0x10000;
+ dst_mul = dst_alpha;
+ }
+ else
+ {
+ if (depth == 8)
+ {
+ tmp = dstptr[n_chan];
+ /* range 0..0xff */
+ dst_alpha = (tmp << 8) + tmp + (tmp >> 7);
+ }
+ else /* (depth == 16) */
+ {
+ tmp = ((art_u16 *)dstptr)[n_chan];
+ dst_alpha = (tmp + (tmp >> 15));
+ }
+ if (alpha_type == ART_ALPHA_SEPARATE)
+ dst_mul = dst_alpha;
+ else /* (alpha_type == ART_ALPHA_PREMUL) */
+ dst_mul = 0x10000;
+ }
+ /* dst_alpha is the alpha of the dest pixel,
+ range 0..0x10000 */
+
+ if (depth == 8)
+ {
+ dst_mul *= 0x101;
+ for (j = 0; j < n_chan; j++)
+ dst[j] = (dstptr[j] * dst_mul + 0x8000) >> 16;
+ }
+ else if (buf_depth == 16)
+ {
+ for (j = 0; j < n_chan; j++)
+ dst[j] = (((art_u16 *)dstptr)[j] * dst_mul + 0x8000) >> 16;
+ }
+
+ /* do the compositing, dst = (src over dst) */
+ for (j = 0; j < n_chan; j++)
+ {
+ art_u32 srcv, dstv;
+ art_u32 tmp;
+
+ srcv = src[j];
+ dstv = dst[j];
+ tmp = ((dstv * (0x10000 - src_alpha) + 0x8000) >> 16) + srcv;
+ tmp -= tmp >> 16;
+ dst[j] = tmp;
+ }
+
+ if (alpha_type == ART_ALPHA_NONE)
+ {
+ if (depth == 8)
+ dst_mul = 0xff;
+ else /* (depth == 16) */
+ dst_mul = 0xffff;
+ }
+ else
+ {
+ if (src_alpha >= 0x10000)
+ dst_alpha = 0x10000;
+ else
+ dst_alpha += ((((0x10000 - dst_alpha) * src_alpha) >> 8) + 0x80) >> 8;
+ if (alpha_type == ART_ALPHA_PREMUL || dst_alpha == 0)
+ {
+ if (depth == 8)
+ dst_mul = 0xff;
+ else /* (depth == 16) */
+ dst_mul = 0xffff;
+ }
+ else /* (ALPHA_TYPE == ART_ALPHA_SEPARATE && dst_alpha != 0) */
+ {
+ if (depth == 8)
+ dst_mul = 0xff0000 / dst_alpha;
+ else /* (depth == 16) */
+ dst_mul = 0xffff0000 / dst_alpha;
+ }
+ }
+ if (depth == 8)
+ {
+ for (j = 0; j < n_chan; j++)
+ dstptr[j] = (dst[j] * dst_mul + 0x8000) >> 16;
+ if (alpha_type != ART_ALPHA_NONE)
+ dstptr[n_chan] = (dst_alpha * 0xff + 0x8000) >> 16;
+ }
+ else if (depth == 16)
+ {
+ for (j = 0; j < n_chan; j++)
+ ((art_u16 *)dstptr)[j] = (dst[j] * dst_mul + 0x8000) >> 16;
+ if (alpha_type != ART_ALPHA_NONE)
+ ((art_u16 *)dstptr)[n_chan] = (dst_alpha * 0xffff + 0x8000) >> 16;
+ }
+ dstptr += dst_pixstride;
+ }
+ }
+}
+
+const ArtRenderCallback art_render_composite_obj =
+{
+ art_render_composite,
+ art_render_nop_done
+};
+
+static void
+art_render_composite_8 (ArtRenderCallback *self, ArtRender *render,
+ art_u8 *dest, int y)
+{
+ ArtRenderMaskRun *run = render->run;
+ int n_run = render->n_run;
+ int x0 = render->x0;
+ int x;
+ int run_x0, run_x1;
+ art_u8 *alpha_buf = render->alpha_buf;
+ art_u8 *image_buf = render->image_buf;
+ int i, j;
+ art_u32 tmp;
+ art_u32 run_alpha;
+ art_u32 alpha;
+ int image_ix;
+ int n_chan = render->n_chan;
+ ArtAlphaType alpha_type = render->alpha_type;
+ int n_ch = n_chan + (alpha_type != ART_ALPHA_NONE);
+ int dst_pixstride = n_ch;
+ ArtAlphaType buf_alpha = render->buf_alpha;
+ int buf_n_ch = n_chan + (buf_alpha != ART_ALPHA_NONE);
+ int buf_pixstride = buf_n_ch;
+ art_u8 *bufptr;
+ art_u32 src_alpha;
+ art_u32 src_mul;
+ art_u8 *dstptr;
+ art_u32 dst_alpha;
+ art_u32 dst_mul, dst_save_mul;
+
+ image_ix = 0;
+ for (i = 0; i < n_run - 1; i++)
+ {
+ run_x0 = run[i].x;
+ run_x1 = run[i + 1].x;
+ tmp = run[i].alpha;
+ if (tmp < 0x10000)
+ continue;
+
+ run_alpha = (tmp + (tmp >> 8) + (tmp >> 16) - 0x8000) >> 8; /* range [0 .. 0x10000] */
+ bufptr = image_buf + (run_x0 - x0) * buf_pixstride;
+ dstptr = dest + (run_x0 - x0) * dst_pixstride;
+ for (x = run_x0; x < run_x1; x++)
+ {
+ if (alpha_buf)
+ {
+ tmp = run_alpha * alpha_buf[x - x0] + 0x80;
+ /* range 0x80 .. 0xff0080 */
+ alpha = (tmp + (tmp >> 8) + (tmp >> 16)) >> 8;
+ }
+ else
+ alpha = run_alpha;
+ /* alpha is run_alpha * alpha_buf[x], range 0 .. 0x10000 */
+
+ /* convert (src pixel * alpha) to premul alpha form,
+ store in src as 0..0xffff range */
+ if (buf_alpha == ART_ALPHA_NONE)
+ {
+ src_alpha = alpha;
+ src_mul = src_alpha;
+ }
+ else
+ {
+ tmp = alpha * bufptr[n_chan] + 0x80;
+ /* range 0x80 .. 0xff0080 */
+ src_alpha = (tmp + (tmp >> 8) + (tmp >> 16)) >> 8;
+
+ if (buf_alpha == ART_ALPHA_SEPARATE)
+ src_mul = src_alpha;
+ else /* buf_alpha == (ART_ALPHA_PREMUL) */
+ src_mul = alpha;
+ }
+ /* src_alpha is the (alpha of the source pixel * alpha),
+ range 0..0x10000 */
+
+ src_mul *= 0x101;
+
+ if (alpha_type == ART_ALPHA_NONE)
+ {
+ dst_alpha = 0x10000;
+ dst_mul = dst_alpha;
+ }
+ else
+ {
+ tmp = dstptr[n_chan];
+ /* range 0..0xff */
+ dst_alpha = (tmp << 8) + tmp + (tmp >> 7);
+ if (alpha_type == ART_ALPHA_SEPARATE)
+ dst_mul = dst_alpha;
+ else /* (alpha_type == ART_ALPHA_PREMUL) */
+ dst_mul = 0x10000;
+ }
+ /* dst_alpha is the alpha of the dest pixel,
+ range 0..0x10000 */
+
+ dst_mul *= 0x101;
+
+ if (alpha_type == ART_ALPHA_NONE)
+ {
+ dst_save_mul = 0xff;
+ }
+ else
+ {
+ if (src_alpha >= 0x10000)
+ dst_alpha = 0x10000;
+ else
+ dst_alpha += ((((0x10000 - dst_alpha) * src_alpha) >> 8) + 0x80) >> 8;
+ if (alpha_type == ART_ALPHA_PREMUL || dst_alpha == 0)
+ {
+ dst_save_mul = 0xff;
+ }
+ else /* (ALPHA_TYPE == ART_ALPHA_SEPARATE && dst_alpha != 0) */
+ {
+ dst_save_mul = 0xff0000 / dst_alpha;
+ }
+ }
+
+ for (j = 0; j < n_chan; j++)
+ {
+ art_u32 src, dst;
+ art_u32 tmp;
+
+ src = (bufptr[j] * src_mul + 0x8000) >> 16;
+ dst = (dstptr[j] * dst_mul + 0x8000) >> 16;
+ tmp = ((dst * (0x10000 - src_alpha) + 0x8000) >> 16) + src;
+ tmp -= tmp >> 16;
+ dstptr[j] = (tmp * dst_save_mul + 0x8000) >> 16;
+ }
+ if (alpha_type != ART_ALPHA_NONE)
+ dstptr[n_chan] = (dst_alpha * 0xff + 0x8000) >> 16;
+
+ bufptr += buf_pixstride;
+ dstptr += dst_pixstride;
+ }
+ }
+}
+
+const ArtRenderCallback art_render_composite_8_obj =
+{
+ art_render_composite_8,
+ art_render_nop_done
+};
+
+
+/* Assumes:
+ * alpha_buf is NULL
+ * buf_alpha = ART_ALPHA_NONE (source)
+ * alpha_type = ART_ALPHA_SEPARATE (dest)
+ * n_chan = 3;
+ */
+static void
+art_render_composite_8_opt1 (ArtRenderCallback *self, ArtRender *render,
+ art_u8 *dest, int y)
+{
+ ArtRenderMaskRun *run = render->run;
+ int n_run = render->n_run;
+ int x0 = render->x0;
+ int x;
+ int run_x0, run_x1;
+ art_u8 *image_buf = render->image_buf;
+ int i, j;
+ art_u32 tmp;
+ art_u32 run_alpha;
+ int image_ix;
+ art_u8 *bufptr;
+ art_u32 src_mul;
+ art_u8 *dstptr;
+ art_u32 dst_alpha;
+ art_u32 dst_mul, dst_save_mul;
+
+ image_ix = 0;
+ for (i = 0; i < n_run - 1; i++)
+ {
+ run_x0 = run[i].x;
+ run_x1 = run[i + 1].x;
+ tmp = run[i].alpha;
+ if (tmp < 0x10000)
+ continue;
+
+ run_alpha = (tmp + (tmp >> 8) + (tmp >> 16) - 0x8000) >> 8; /* range [0 .. 0x10000] */
+ bufptr = image_buf + (run_x0 - x0) * 3;
+ dstptr = dest + (run_x0 - x0) * 4;
+ if (run_alpha == 0x10000)
+ {
+ for (x = run_x0; x < run_x1; x++)
+ {
+ *dstptr++ = *bufptr++;
+ *dstptr++ = *bufptr++;
+ *dstptr++ = *bufptr++;
+ *dstptr++ = 0xff;
+ }
+ }
+ else
+ {
+ for (x = run_x0; x < run_x1; x++)
+ {
+ src_mul = run_alpha * 0x101;
+
+ tmp = dstptr[3];
+ /* range 0..0xff */
+ dst_alpha = (tmp << 8) + tmp + (tmp >> 7);
+ dst_mul = dst_alpha;
+ /* dst_alpha is the alpha of the dest pixel,
+ range 0..0x10000 */
+
+ dst_mul *= 0x101;
+
+ dst_alpha += ((((0x10000 - dst_alpha) * run_alpha) >> 8) + 0x80) >> 8;
+ if (dst_alpha == 0)
+ dst_save_mul = 0xff;
+ else /* (dst_alpha != 0) */
+ dst_save_mul = 0xff0000 / dst_alpha;
+
+ for (j = 0; j < 3; j++)
+ {
+ art_u32 src, dst;
+ art_u32 tmp;
+
+ src = (bufptr[j] * src_mul + 0x8000) >> 16;
+ dst = (dstptr[j] * dst_mul + 0x8000) >> 16;
+ tmp = ((dst * (0x10000 - run_alpha) + 0x8000) >> 16) + src;
+ tmp -= tmp >> 16;
+ dstptr[j] = (tmp * dst_save_mul + 0x8000) >> 16;
+ }
+ dstptr[3] = (dst_alpha * 0xff + 0x8000) >> 16;
+
+ bufptr += 3;
+ dstptr += 4;
+ }
+ }
+ }
+}
+
+
+const ArtRenderCallback art_render_composite_8_opt1_obj =
+{
+ art_render_composite_8_opt1,
+ art_render_nop_done
+};
+
+/* Assumes:
+ * alpha_buf is NULL
+ * buf_alpha = ART_ALPHA_PREMUL (source)
+ * alpha_type = ART_ALPHA_SEPARATE (dest)
+ * n_chan = 3;
+ */
+static void
+art_render_composite_8_opt2 (ArtRenderCallback *self, ArtRender *render,
+ art_u8 *dest, int y)
+{
+ ArtRenderMaskRun *run = render->run;
+ int n_run = render->n_run;
+ int x0 = render->x0;
+ int x;
+ int run_x0, run_x1;
+ art_u8 *image_buf = render->image_buf;
+ int i, j;
+ art_u32 tmp;
+ art_u32 run_alpha;
+ int image_ix;
+ art_u8 *bufptr;
+ art_u32 src_alpha;
+ art_u32 src_mul;
+ art_u8 *dstptr;
+ art_u32 dst_alpha;
+ art_u32 dst_mul, dst_save_mul;
+
+ image_ix = 0;
+ for (i = 0; i < n_run - 1; i++)
+ {
+ run_x0 = run[i].x;
+ run_x1 = run[i + 1].x;
+ tmp = run[i].alpha;
+ if (tmp < 0x10000)
+ continue;
+
+ run_alpha = (tmp + (tmp >> 8) + (tmp >> 16) - 0x8000) >> 8; /* range [0 .. 0x10000] */
+ bufptr = image_buf + (run_x0 - x0) * 4;
+ dstptr = dest + (run_x0 - x0) * 4;
+ if (run_alpha == 0x10000)
+ {
+ for (x = run_x0; x < run_x1; x++)
+ {
+ src_alpha = (bufptr[3] << 8) + bufptr[3] + (bufptr[3] >> 7);
+ /* src_alpha is the (alpha of the source pixel),
+ range 0..0x10000 */
+
+ dst_alpha = (dstptr[3] << 8) + dstptr[3] + (dstptr[3] >> 7);
+ /* dst_alpha is the alpha of the dest pixel,
+ range 0..0x10000 */
+
+ dst_mul = dst_alpha*0x101;
+
+ if (src_alpha >= 0x10000)
+ dst_alpha = 0x10000;
+ else
+ dst_alpha += ((((0x10000 - dst_alpha) * src_alpha) >> 8) + 0x80) >> 8;
+
+ if (dst_alpha == 0)
+ dst_save_mul = 0xff;
+ else /* dst_alpha != 0) */
+ dst_save_mul = 0xff0000 / dst_alpha;
+
+ for (j = 0; j < 3; j++)
+ {
+ art_u32 src, dst;
+ art_u32 tmp;
+
+ src = (bufptr[j] << 8) | bufptr[j];
+ dst = (dstptr[j] * dst_mul + 0x8000) >> 16;
+ tmp = ((dst * (0x10000 - src_alpha) + 0x8000) >> 16) + src;
+ tmp -= tmp >> 16;
+ dstptr[j] = (tmp * dst_save_mul + 0x8000) >> 16;
+ }
+ dstptr[3] = (dst_alpha * 0xff + 0x8000) >> 16;
+
+ bufptr += 4;
+ dstptr += 4;
+ }
+ }
+ else
+ {
+ for (x = run_x0; x < run_x1; x++)
+ {
+ tmp = run_alpha * bufptr[3] + 0x80;
+ /* range 0x80 .. 0xff0080 */
+ src_alpha = (tmp + (tmp >> 8) + (tmp >> 16)) >> 8;
+ /* src_alpha is the (alpha of the source pixel * alpha),
+ range 0..0x10000 */
+
+ src_mul = run_alpha * 0x101;
+
+ tmp = dstptr[3];
+ /* range 0..0xff */
+ dst_alpha = (tmp << 8) + tmp + (tmp >> 7);
+ dst_mul = dst_alpha;
+ /* dst_alpha is the alpha of the dest pixel,
+ range 0..0x10000 */
+
+ dst_mul *= 0x101;
+
+ if (src_alpha >= 0x10000)
+ dst_alpha = 0x10000;
+ else
+ dst_alpha += ((((0x10000 - dst_alpha) * src_alpha) >> 8) + 0x80) >> 8;
+
+ if (dst_alpha == 0)
+ {
+ dst_save_mul = 0xff;
+ }
+ else /* dst_alpha != 0) */
+ {
+ dst_save_mul = 0xff0000 / dst_alpha;
+ }
+
+ for (j = 0; j < 3; j++)
+ {
+ art_u32 src, dst;
+ art_u32 tmp;
+
+ src = (bufptr[j] * src_mul + 0x8000) >> 16;
+ dst = (dstptr[j] * dst_mul + 0x8000) >> 16;
+ tmp = ((dst * (0x10000 - src_alpha) + 0x8000) >> 16) + src;
+ tmp -= tmp >> 16;
+ dstptr[j] = (tmp * dst_save_mul + 0x8000) >> 16;
+ }
+ dstptr[3] = (dst_alpha * 0xff + 0x8000) >> 16;
+
+ bufptr += 4;
+ dstptr += 4;
+ }
+ }
+ }
+}
+
+const ArtRenderCallback art_render_composite_8_opt2_obj =
+{
+ art_render_composite_8_opt2,
+ art_render_nop_done
+};
+
+
+/* todo: inline */
+static ArtRenderCallback *
+art_render_choose_compositing_callback (ArtRender *render)
+{
+ if (render->depth == 8 && render->buf_depth == 8)
+ {
+ if (render->n_chan == 3 &&
+ render->alpha_buf == NULL &&
+ render->alpha_type == ART_ALPHA_SEPARATE)
+ {
+ if (render->buf_alpha == ART_ALPHA_NONE)
+ return (ArtRenderCallback *)&art_render_composite_8_opt1_obj;
+ else if (render->buf_alpha == ART_ALPHA_PREMUL)
+ return (ArtRenderCallback *)&art_render_composite_8_opt2_obj;
+ }
+
+ return (ArtRenderCallback *)&art_render_composite_8_obj;
+ }
+ return (ArtRenderCallback *)&art_render_composite_obj;
+}
+
+/**
+ * art_render_invoke_callbacks: Invoke the callbacks in the render object.
+ * @render: The render object.
+ * @y: The current Y coordinate value.
+ *
+ * Invokes the callbacks of the render object in the appropriate
+ * order. Drivers should call this routine once per scanline.
+ *
+ * todo: should management of dest devolve to this routine? very
+ * plausibly yes.
+ **/
+void
+art_render_invoke_callbacks (ArtRender *render, art_u8 *dest, int y)
+{
+ ArtRenderPriv *priv = (ArtRenderPriv *)render;
+ int i;
+
+ for (i = 0; i < priv->n_callbacks; i++)
+ {
+ ArtRenderCallback *callback;
+
+ callback = priv->callbacks[i];
+ callback->render (callback, render, dest, y);
+ }
+}
+
+/**
+ * art_render_invoke: Perform the requested rendering task.
+ * @render: The render object.
+ *
+ * Invokes the renderer and all sources associated with it, to perform
+ * the requested rendering task.
+ **/
+void
+art_render_invoke (ArtRender *render)
+{
+ ArtRenderPriv *priv = (ArtRenderPriv *)render;
+ int width;
+ int best_driver, best_score;
+ int i;
+ int n_callbacks, n_callbacks_max;
+ ArtImageSource *image_source;
+ int image_flags;
+ int buf_depth;
+ ArtAlphaType buf_alpha;
+ art_boolean first = ART_TRUE;
+
+ if (render == NULL)
+ {
+ art_warn ("art_render_invoke: called with render == NULL\n");
+ return;
+ }
+ if (priv->image_source == NULL)
+ {
+ art_warn ("art_render_invoke: no image source given\n");
+ return;
+ }
+
+ width = render->x1 - render->x0;
+
+ render->run = art_new (ArtRenderMaskRun, width + 1);
+
+ /* Elect a mask source as driver. */
+ best_driver = -1;
+ best_score = 0;
+ for (i = 0; i < priv->n_mask_source; i++)
+ {
+ int score;
+ ArtMaskSource *mask_source;
+
+ mask_source = priv->mask_source[i];
+ score = mask_source->can_drive (mask_source, render);
+ if (score > best_score)
+ {
+ best_score = score;
+ best_driver = i;
+ }
+ }
+
+ /* Allocate alpha buffer if needed. */
+ if (priv->n_mask_source > 1 ||
+ (priv->n_mask_source == 1 && best_driver < 0))
+ {
+ render->alpha_buf = art_new (art_u8, (width * render->depth) >> 3);
+ }
+
+ /* Negotiate image rendering and compositing. */
+ image_source = priv->image_source;
+ image_source->negotiate (image_source, render, &image_flags, &buf_depth,
+ &buf_alpha);
+
+ /* Build callback list. */
+ n_callbacks_max = priv->n_mask_source + 3;
+ priv->callbacks = art_new (ArtRenderCallback *, n_callbacks_max);
+ n_callbacks = 0;
+ for (i = 0; i < priv->n_mask_source; i++)
+ if (i != best_driver)
+ {
+ ArtMaskSource *mask_source = priv->mask_source[i];
+
+ mask_source->prepare (mask_source, render, first);
+ first = ART_FALSE;
+ priv->callbacks[n_callbacks++] = &mask_source->super;
+ }
+
+ if (render->clear && !(image_flags & ART_IMAGE_SOURCE_CAN_CLEAR))
+ priv->callbacks[n_callbacks++] =
+ art_render_choose_clear_callback (render);
+
+ priv->callbacks[n_callbacks++] = &image_source->super;
+
+ /* Allocate image buffer and add compositing callback if needed. */
+ if (!(image_flags & ART_IMAGE_SOURCE_CAN_COMPOSITE))
+ {
+ int bytespp = ((render->n_chan + (buf_alpha != ART_ALPHA_NONE)) *
+ buf_depth) >> 3;
+ render->buf_depth = buf_depth;
+ render->buf_alpha = buf_alpha;
+ render->image_buf = art_new (art_u8, width * bytespp);
+ priv->callbacks[n_callbacks++] =
+ art_render_choose_compositing_callback (render);
+ }
+
+ priv->n_callbacks = n_callbacks;
+
+ if (render->need_span)
+ render->span_x = art_new (int, width + 1);
+
+ /* Invoke the driver */
+ if (best_driver >= 0)
+ {
+ ArtMaskSource *driver;
+
+ driver = priv->mask_source[best_driver];
+ driver->invoke_driver (driver, render);
+ }
+ else
+ {
+ art_u8 *dest_ptr = render->pixels;
+ int y;
+
+ /* Dummy driver */
+ render->n_run = 2;
+ render->run[0].x = render->x0;
+ render->run[0].alpha = 0x8000 + 0xff * render->opacity;
+ render->run[1].x = render->x1;
+ render->run[1].alpha = 0x8000;
+ if (render->need_span)
+ {
+ render->n_span = 2;
+ render->span_x[0] = render->x0;
+ render->span_x[1] = render->x1;
+ }
+ for (y = render->y0; y < render->y1; y++)
+ {
+ art_render_invoke_callbacks (render, dest_ptr, y);
+ dest_ptr += render->rowstride;
+ }
+ }
+
+ if (priv->mask_source != NULL)
+ art_free (priv->mask_source);
+
+ /* clean up callbacks */
+ for (i = 0; i < priv->n_callbacks; i++)
+ {
+ ArtRenderCallback *callback;
+
+ callback = priv->callbacks[i];
+ callback->done (callback, render);
+ }
+
+ /* Tear down object */
+ if (render->alpha_buf != NULL)
+ art_free (render->alpha_buf);
+ if (render->image_buf != NULL)
+ art_free (render->image_buf);
+ art_free (render->run);
+ if (render->span_x != NULL)
+ art_free (render->span_x);
+ art_free (priv->callbacks);
+ art_free (render);
+}
+
+/**
+ * art_render_mask_solid: Add a solid translucent mask.
+ * @render: The render object.
+ * @opacity: Opacity in [0..0x10000] form.
+ *
+ * Adds a translucent mask to the rendering object.
+ **/
+void
+art_render_mask_solid (ArtRender *render, int opacity)
+{
+ art_u32 old_opacity = render->opacity;
+ art_u32 new_opacity_tmp;
+
+ if (opacity == 0x10000)
+ /* avoid potential overflow */
+ return;
+ new_opacity_tmp = old_opacity * (art_u32)opacity + 0x8000;
+ render->opacity = new_opacity_tmp >> 16;
+}
+
+/**
+ * art_render_add_mask_source: Add a mask source to the render object.
+ * @render: Render object.
+ * @mask_source: Mask source to add.
+ *
+ * This routine adds a mask source to the render object. In general,
+ * client api's for adding mask sources should just take a render object,
+ * then the mask source creation function should call this function.
+ * Clients should never have to call this function directly, unless of
+ * course they're creating custom mask sources.
+ **/
+void
+art_render_add_mask_source (ArtRender *render, ArtMaskSource *mask_source)
+{
+ ArtRenderPriv *priv = (ArtRenderPriv *)render;
+ int n_mask_source = priv->n_mask_source++;
+
+ if (n_mask_source == 0)
+ priv->mask_source = art_new (ArtMaskSource *, 1);
+ /* This predicate is true iff n_mask_source is a power of two */
+ else if (!(n_mask_source & (n_mask_source - 1)))
+ priv->mask_source = art_renew (priv->mask_source, ArtMaskSource *,
+ n_mask_source << 1);
+
+ priv->mask_source[n_mask_source] = mask_source;
+}
+
+/**
+ * art_render_add_image_source: Add a mask source to the render object.
+ * @render: Render object.
+ * @image_source: Image source to add.
+ *
+ * This routine adds an image source to the render object. In general,
+ * client api's for adding image sources should just take a render
+ * object, then the mask source creation function should call this
+ * function. Clients should never have to call this function
+ * directly, unless of course they're creating custom image sources.
+ **/
+void
+art_render_add_image_source (ArtRender *render, ArtImageSource *image_source)
+{
+ ArtRenderPriv *priv = (ArtRenderPriv *)render;
+
+ if (priv->image_source != NULL)
+ {
+ art_warn ("art_render_add_image_source: image source already present.\n");
+ return;
+ }
+ priv->image_source = image_source;
+}
+
+/* Solid image source object and methods. Perhaps this should go into a
+ separate file. */
+
+typedef struct _ArtImageSourceSolid ArtImageSourceSolid;
+
+struct _ArtImageSourceSolid {
+ ArtImageSource super;
+ ArtPixMaxDepth color[ART_MAX_CHAN];
+ art_u32 *rgbtab;
+ art_boolean init;
+};
+
+static void
+art_render_image_solid_done (ArtRenderCallback *self, ArtRender *render)
+{
+ ArtImageSourceSolid *z = (ArtImageSourceSolid *)self;
+
+ if (z->rgbtab != NULL)
+ art_free (z->rgbtab);
+ art_free (self);
+}
+
+static void
+art_render_image_solid_rgb8_opaq_init (ArtImageSourceSolid *self, ArtRender *render)
+{
+ ArtImageSourceSolid *z = (ArtImageSourceSolid *)self;
+ ArtPixMaxDepth color_max;
+ int r_fg, g_fg, b_fg;
+ int r_bg, g_bg, b_bg;
+ int r, g, b;
+ int dr, dg, db;
+ int i;
+ int tmp;
+ art_u32 *rgbtab;
+
+ rgbtab = art_new (art_u32, 256);
+ z->rgbtab = rgbtab;
+
+ color_max = self->color[0];
+ r_fg = ART_PIX_8_FROM_MAX (color_max);
+ color_max = self->color[1];
+ g_fg = ART_PIX_8_FROM_MAX (color_max);
+ color_max = self->color[2];
+ b_fg = ART_PIX_8_FROM_MAX (color_max);
+
+ color_max = render->clear_color[0];
+ r_bg = ART_PIX_8_FROM_MAX (color_max);
+ color_max = render->clear_color[1];
+ g_bg = ART_PIX_8_FROM_MAX (color_max);
+ color_max = render->clear_color[2];
+ b_bg = ART_PIX_8_FROM_MAX (color_max);
+
+ r = (r_bg << 16) + 0x8000;
+ g = (g_bg << 16) + 0x8000;
+ b = (b_bg << 16) + 0x8000;
+ tmp = ((r_fg - r_bg) << 16) + 0x80;
+ dr = (tmp + (tmp >> 8)) >> 8;
+ tmp = ((g_fg - g_bg) << 16) + 0x80;
+ dg = (tmp + (tmp >> 8)) >> 8;
+ tmp = ((b_fg - b_bg) << 16) + 0x80;
+ db = (tmp + (tmp >> 8)) >> 8;
+
+ for (i = 0; i < 256; i++)
+ {
+ rgbtab[i] = (r & 0xff0000) | ((g & 0xff0000) >> 8) | (b >> 16);
+ r += dr;
+ g += dg;
+ b += db;
+ }
+}
+
+static void
+art_render_image_solid_rgb8_opaq (ArtRenderCallback *self, ArtRender *render,
+ art_u8 *dest, int y)
+{
+ ArtImageSourceSolid *z = (ArtImageSourceSolid *)self;
+ ArtRenderMaskRun *run = render->run;
+ int n_run = render->n_run;
+ art_u32 *rgbtab = z->rgbtab;
+ art_u32 rgb;
+ int x0 = render->x0;
+ int x1 = render->x1;
+ int run_x0, run_x1;
+ int i;
+ int ix;
+
+ if (n_run > 0)
+ {
+ run_x1 = run[0].x;
+ if (run_x1 > x0)
+ {
+ rgb = rgbtab[0];
+ art_rgb_fill_run (dest,
+ rgb >> 16, (rgb >> 8) & 0xff, rgb & 0xff,
+ run_x1 - x0);
+ }
+ for (i = 0; i < n_run - 1; i++)
+ {
+ run_x0 = run_x1;
+ run_x1 = run[i + 1].x;
+ rgb = rgbtab[(run[i].alpha >> 16) & 0xff];
+ ix = (run_x0 - x0) * 3;
+#define OPTIMIZE_LEN_1
+#ifdef OPTIMIZE_LEN_1
+ if (run_x1 - run_x0 == 1)
+ {
+ dest[ix] = rgb >> 16;
+ dest[ix + 1] = (rgb >> 8) & 0xff;
+ dest[ix + 2] = rgb & 0xff;
+ }
+ else
+ {
+ art_rgb_fill_run (dest + ix,
+ rgb >> 16, (rgb >> 8) & 0xff, rgb & 0xff,
+ run_x1 - run_x0);
+ }
+#else
+ art_rgb_fill_run (dest + ix,
+ rgb >> 16, (rgb >> 8) & 0xff, rgb & 0xff,
+ run_x1 - run_x0);
+#endif
+ }
+ }
+ else
+ {
+ run_x1 = x0;
+ }
+ if (run_x1 < x1)
+ {
+ rgb = rgbtab[0];
+ art_rgb_fill_run (dest + (run_x1 - x0) * 3,
+ rgb >> 16, (rgb >> 8) & 0xff, rgb & 0xff,
+ x1 - run_x1);
+ }
+}
+
+static void
+art_render_image_solid_rgb8 (ArtRenderCallback *self, ArtRender *render,
+ art_u8 *dest, int y)
+{
+ ArtImageSourceSolid *z = (ArtImageSourceSolid *)self;
+ int width = render->x1 - render->x0;
+ art_u8 r, g, b;
+ ArtPixMaxDepth color_max;
+
+ /* todo: replace this simple test with real sparseness */
+ if (z->init)
+ return;
+ z->init = ART_TRUE;
+
+ color_max = z->color[0];
+ r = ART_PIX_8_FROM_MAX (color_max);
+ color_max = z->color[1];
+ g = ART_PIX_8_FROM_MAX (color_max);
+ color_max = z->color[2];
+ b = ART_PIX_8_FROM_MAX (color_max);
+
+ art_rgb_fill_run (render->image_buf, r, g, b, width);
+}
+
+static void
+art_render_image_solid_negotiate (ArtImageSource *self, ArtRender *render,
+ int *p_flags,
+ int *p_buf_depth, ArtAlphaType *p_alpha)
+{
+ ArtImageSourceSolid *z = (ArtImageSourceSolid *)self;
+ int flags = 0;
+ static void (*render_cbk) (ArtRenderCallback *self, ArtRender *render,
+ art_u8 *dest, int y);
+
+ render_cbk = NULL;
+
+ if (render->depth == 8 && render->n_chan == 3 &&
+ render->alpha_type == ART_ALPHA_NONE)
+ {
+ if (render->clear)
+ {
+ render_cbk = art_render_image_solid_rgb8_opaq;
+ flags |= ART_IMAGE_SOURCE_CAN_CLEAR | ART_IMAGE_SOURCE_CAN_COMPOSITE;
+ art_render_image_solid_rgb8_opaq_init (z, render);
+ }
+ }
+ if (render_cbk == NULL)
+ {
+ if (render->depth == 8)
+ {
+ render_cbk = art_render_image_solid_rgb8;
+ *p_buf_depth = 8;
+ *p_alpha = ART_ALPHA_NONE; /* todo */
+ }
+ }
+ /* todo: general case */
+ self->super.render = render_cbk;
+ *p_flags = flags;
+}
+
+/**
+ * art_render_image_solid: Add a solid color image source.
+ * @render: The render object.
+ * @color: Color.
+ *
+ * Adds an image source with the solid color given by @color. The
+ * color need not be retained in memory after this call.
+ **/
+void
+art_render_image_solid (ArtRender *render, ArtPixMaxDepth *color)
+{
+ ArtImageSourceSolid *image_source;
+ int i;
+
+ image_source = art_new (ArtImageSourceSolid, 1);
+ image_source->super.super.render = NULL;
+ image_source->super.super.done = art_render_image_solid_done;
+ image_source->super.negotiate = art_render_image_solid_negotiate;
+
+ for (i = 0; i < render->n_chan; i++)
+ image_source->color[i] = color[i];
+
+ image_source->rgbtab = NULL;
+ image_source->init = ART_FALSE;
+
+ art_render_add_image_source (render, &image_source->super);
+}
diff -Nru swftools-0.9.2+ds1/lib/art/art_render_gradient.c swftools-0.9.1/lib/art/art_render_gradient.c
--- swftools-0.9.2+ds1/lib/art/art_render_gradient.c 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/art/art_render_gradient.c 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,716 @@
+/*
+ * art_render_gradient.c: Gradient image source for modular rendering.
+ *
+ * Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 2000 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Authors: Raph Levien
+ * Alexander Larsson
+ */
+
+#include "config.h"
+#include "art_render_gradient.h"
+
+#include
+#include
+#include
+#include
+#include
+
+/* Hack to find out how to define alloca on different platforms.
+ * Modified version of glib/galloca.h.
+ */
+
+#ifdef __GNUC__
+/* GCC does the right thing */
+# undef alloca
+# define alloca(size) __builtin_alloca (size)
+#elif defined (HAVE_ALLOCA_H)
+/* a native and working alloca.h is there */
+# include
+#else /* !__GNUC__ && !HAVE_ALLOCA_H */
+# ifdef _MSC_VER
+# include
+# define alloca _alloca
+# else /* !_MSC_VER */
+# ifdef _AIX
+ #pragma alloca
+# else /* !_AIX */
+# ifndef alloca /* predefined by HP cc +Olibcalls */
+char *alloca ();
+# endif /* !alloca */
+# endif /* !_AIX */
+# endif /* !_MSC_VER */
+#endif /* !__GNUC__ && !HAVE_ALLOCA_H */
+
+#undef DEBUG_SPEW
+
+typedef struct _ArtImageSourceGradLin ArtImageSourceGradLin;
+typedef struct _ArtImageSourceGradRad ArtImageSourceGradRad;
+
+/* The stops will be copied right after this structure */
+struct _ArtImageSourceGradLin {
+ ArtImageSource super;
+ ArtGradientLinear gradient;
+ ArtGradientStop stops[1];
+};
+
+/* The stops will be copied right after this structure */
+struct _ArtImageSourceGradRad {
+ ArtImageSource super;
+ ArtGradientRadial gradient;
+ double a;
+ ArtGradientStop stops[1];
+};
+
+#define EPSILON 1e-6
+
+#ifndef MAX
+#define MAX(a, b) (((a) > (b)) ? (a) : (b))
+#endif /* MAX */
+
+#ifndef MIN
+#define MIN(a, b) (((a) < (b)) ? (a) : (b))
+#endif /* MIN */
+
+static void
+art_rgba_gradient_run (art_u8 *buf,
+ art_u8 *color1,
+ art_u8 *color2,
+ int len)
+{
+ int i;
+ int r, g, b, a;
+ int dr, dg, db, da;
+
+#ifdef DEBUG_SPEW
+ printf ("gradient run from %3d %3d %3d %3d to %3d %3d %3d %3d in %d pixels\n",
+ color1[0], color1[1], color1[2], color1[3],
+ color2[0], color2[1], color2[2], color2[3],
+ len);
+#endif
+
+ r = (color1[0] << 16) + 0x8000;
+ g = (color1[1] << 16) + 0x8000;
+ b = (color1[2] << 16) + 0x8000;
+ a = (color1[3] << 16) + 0x8000;
+ dr = ((color2[0] - color1[0]) << 16) / len;
+ dg = ((color2[1] - color1[1]) << 16) / len;
+ db = ((color2[2] - color1[2]) << 16) / len;
+ da = ((color2[3] - color1[3]) << 16) / len;
+
+ for (i = 0; i < len; i++)
+ {
+ *buf++ = (r>>16);
+ *buf++ = (g>>16);
+ *buf++ = (b>>16);
+ *buf++ = (a>>16);
+
+ r += dr;
+ g += dg;
+ b += db;
+ a += da;
+ }
+}
+
+static void
+calc_color_at (ArtGradientStop *stops,
+ int n_stops,
+ ArtGradientSpread spread,
+ double offset,
+ double offset_fraction,
+ int favor_start,
+ int ix,
+ art_u8 *color)
+{
+ double off0, off1;
+ int j;
+
+ if (spread == ART_GRADIENT_PAD)
+ {
+ if (offset < 0.0)
+ {
+ color[0] = ART_PIX_8_FROM_MAX (stops[0].color[0]);
+ color[1] = ART_PIX_8_FROM_MAX (stops[0].color[1]);
+ color[2] = ART_PIX_8_FROM_MAX (stops[0].color[2]);
+ color[3] = ART_PIX_8_FROM_MAX (stops[0].color[3]);
+ return;
+ }
+ if (offset >= 1.0)
+ {
+ color[0] = ART_PIX_8_FROM_MAX (stops[n_stops-1].color[0]);
+ color[1] = ART_PIX_8_FROM_MAX (stops[n_stops-1].color[1]);
+ color[2] = ART_PIX_8_FROM_MAX (stops[n_stops-1].color[2]);
+ color[3] = ART_PIX_8_FROM_MAX (stops[n_stops-1].color[3]);
+ return;
+ }
+ }
+
+ if (ix > 0 && ix < n_stops)
+ {
+ off0 = stops[ix - 1].offset;
+ off1 = stops[ix].offset;
+ if (fabs (off1 - off0) > EPSILON)
+ {
+ double interp;
+ double o;
+ o = offset_fraction;
+
+ if ((fabs (o) < EPSILON) && (!favor_start))
+ o = 1.0;
+ else if ((fabs (o-1.0) < EPSILON) && (favor_start))
+ o = 0.0;
+
+ /*
+ if (offset_fraction == 0.0 && !favor_start)
+ offset_fraction = 1.0;
+ */
+
+ interp = (o - off0) / (off1 - off0);
+ for (j = 0; j < 4; j++)
+ {
+ int z0, z1;
+ int z;
+ z0 = stops[ix - 1].color[j];
+ z1 = stops[ix].color[j];
+ z = floor (z0 + (z1 - z0) * interp + 0.5);
+ color[j] = ART_PIX_8_FROM_MAX (z);
+ }
+ return;
+ }
+ /* If offsets are too close to safely do the division, just
+ pick the ix color. */
+ color[0] = ART_PIX_8_FROM_MAX (stops[ix].color[0]);
+ color[1] = ART_PIX_8_FROM_MAX (stops[ix].color[1]);
+ color[2] = ART_PIX_8_FROM_MAX (stops[ix].color[2]);
+ color[3] = ART_PIX_8_FROM_MAX (stops[ix].color[3]);
+ return;
+ }
+
+ printf ("WARNING! bad ix %d in calc_color_at() [internal error]\n", ix);
+ assert (0);
+}
+
+static void
+art_render_gradient_linear_render_8 (ArtRenderCallback *self,
+ ArtRender *render,
+ art_u8 *dest, int y)
+{
+ ArtImageSourceGradLin *z = (ArtImageSourceGradLin *)self;
+ const ArtGradientLinear *gradient = &(z->gradient);
+ int i;
+ int width = render->x1 - render->x0;
+ int len;
+ double offset, d_offset;
+ double offset_fraction;
+ int next_stop;
+ int ix;
+ art_u8 color1[4], color2[4];
+ int n_stops = gradient->n_stops;
+ int extra_stops;
+ ArtGradientStop *stops = gradient->stops;
+ ArtGradientStop *tmp_stops;
+ art_u8 *bufp = render->image_buf;
+ ArtGradientSpread spread = gradient->spread;
+
+#ifdef DEBUG_SPEW
+ printf ("x1: %d, x2: %d, y: %d\n", render->x0, render->x1, y);
+ printf ("spread: %d, stops:", gradient->spread);
+ for (i=0;istops[i].offset);
+ }
+ printf ("\n");
+ printf ("a: %f, b: %f, c: %f\n", gradient->a, gradient->b, gradient->c);
+#endif
+
+ offset = render->x0 * gradient->a + y * gradient->b + gradient->c;
+ d_offset = gradient->a;
+
+ /* We need to force the gradient to extend the whole 0..1 segment,
+ because the rest of the code doesn't handle partial gradients
+ correctly */
+ if ((gradient->stops[0].offset > EPSILON /* == 0.0 */) ||
+ (gradient->stops[n_stops-1].offset < (1.0 - EPSILON)))
+ {
+ extra_stops = 0;
+ tmp_stops = stops = (ArtGradientStop*)alloca (sizeof (ArtGradientStop) * (n_stops + 2));
+ if (gradient->stops[0].offset > EPSILON /* 0.0 */)
+ {
+ memcpy (tmp_stops, gradient->stops, sizeof (ArtGradientStop));
+ tmp_stops[0].offset = 0.0;
+ tmp_stops += 1;
+ extra_stops++;
+ }
+ memcpy (tmp_stops, gradient->stops, sizeof (ArtGradientStop) * n_stops);
+ if (gradient->stops[n_stops-1].offset < (1.0 - EPSILON))
+ {
+ tmp_stops += n_stops;
+ memcpy (tmp_stops, &gradient->stops[n_stops-1], sizeof (ArtGradientStop));
+ tmp_stops[0].offset = 1.0;
+ extra_stops++;
+ }
+ n_stops += extra_stops;
+
+
+#ifdef DEBUG_SPEW
+ printf ("start/stop modified stops:");
+ for (i=0;i offset_fraction ||
+ (d_offset < 0.0 && fabs (stops[ix].offset - offset_fraction) < EPSILON))
+ break;
+ if (ix == 0)
+ ix = n_stops - 1;
+ else if (ix == n_stops)
+ ix = n_stops - 1;
+
+#ifdef DEBUG_SPEW
+ printf ("Initial ix: %d\n", ix);
+#endif
+
+ assert (ix > 0);
+ assert (ix < n_stops);
+ assert ((stops[ix-1].offset <= offset_fraction + EPSILON) ||
+ ((stops[ix].offset > (1.0 - EPSILON)) && (offset_fraction < EPSILON /* == 0.0*/)));
+ assert (offset_fraction <= stops[ix].offset);
+ /* FIXME: These asserts may be broken, it is for now
+ safer to not use them. Should be fixed!
+ See bug #121850
+ assert ((offset_fraction != stops[ix-1].offset) ||
+ (d_offset >= 0.0));
+ assert ((offset_fraction != stops[ix].offset) ||
+ (d_offset <= 0.0));
+ */
+
+ while (width > 0)
+ {
+#ifdef DEBUG_SPEW
+ printf ("ix: %d\n", ix);
+ printf ("start offset: %f\n", offset);
+#endif
+ calc_color_at (stops, n_stops,
+ spread,
+ offset,
+ offset_fraction,
+ (d_offset > -EPSILON),
+ ix,
+ color1);
+
+ if (d_offset > 0)
+ next_stop = ix;
+ else
+ next_stop = ix-1;
+
+#ifdef DEBUG_SPEW
+ printf ("next_stop: %d\n", next_stop);
+#endif
+ if (fabs (d_offset) > EPSILON)
+ {
+ double o;
+ o = offset_fraction;
+
+ if ((fabs (o) <= EPSILON) && (ix == n_stops - 1))
+ o = 1.0;
+ else if ((fabs (o-1.0) <= EPSILON) && (ix == 1))
+ o = 0.0;
+
+#ifdef DEBUG_SPEW
+ printf ("o: %f\n", o);
+#endif
+ len = (int)floor (fabs ((stops[next_stop].offset - o) / d_offset)) + 1;
+ len = MAX (len, 0);
+ len = MIN (len, width);
+ }
+ else
+ {
+ len = width;
+ }
+#ifdef DEBUG_SPEW
+ printf ("len: %d\n", len);
+#endif
+ if (len > 0)
+ {
+ offset = offset + (len-1) * d_offset;
+ offset_fraction = offset - floor (offset);
+#ifdef DEBUG_SPEW
+ printf ("end offset: %f, fraction: %f\n", offset, offset_fraction);
+#endif
+ calc_color_at (stops, n_stops,
+ spread,
+ offset,
+ offset_fraction,
+ (d_offset < EPSILON),
+ ix,
+ color2);
+
+ art_rgba_gradient_run (bufp,
+ color1,
+ color2,
+ len);
+ offset += d_offset;
+ offset_fraction = offset - floor (offset);
+ }
+
+ if (d_offset > 0)
+ {
+ do
+ {
+ ix++;
+ if (ix == n_stops)
+ ix = 1;
+ /* Note: offset_fraction can actually be one here on x86 machines that
+ does calculations with extended precision, but later rounds to 64bit.
+ This happens if the 80bit offset_fraction is larger than the
+ largest 64bit double that is less than one.
+ */
+ }
+ while (!((stops[ix-1].offset <= offset_fraction &&
+ offset_fraction < stops[ix].offset) ||
+ (ix == 1 && offset_fraction > (1.0 - EPSILON))));
+ }
+ else
+ {
+ do
+ {
+ ix--;
+ if (ix == 0)
+ ix = n_stops - 1;
+ }
+ while (!((stops[ix-1].offset < offset_fraction &&
+ offset_fraction <= stops[ix].offset) ||
+ (ix == n_stops - 1 && offset_fraction < EPSILON /* == 0.0*/)));
+ }
+
+ bufp += 4*len;
+ width -= len;
+ }
+}
+
+
+/**
+ * art_render_gradient_setpix: Set a gradient pixel.
+ * @render: The render object.
+ * @dst: Pointer to destination (where to store pixel).
+ * @n_stops: Number of stops in @stops.
+ * @stops: The stops for the gradient.
+ * @offset: The offset.
+ *
+ * @n_stops must be > 0.
+ *
+ * Sets a gradient pixel, storing it at @dst.
+ **/
+static void
+art_render_gradient_setpix (ArtRender *render,
+ art_u8 *dst,
+ int n_stops, ArtGradientStop *stops,
+ double offset)
+{
+ int ix;
+ int j;
+ double off0, off1;
+ int n_ch = render->n_chan + 1;
+
+ for (ix = 0; ix < n_stops; ix++)
+ if (stops[ix].offset > offset)
+ break;
+ /* stops[ix - 1].offset < offset < stops[ix].offset */
+ if (ix > 0 && ix < n_stops)
+ {
+ off0 = stops[ix - 1].offset;
+ off1 = stops[ix].offset;
+ if (fabs (off1 - off0) > EPSILON)
+ {
+ double interp;
+
+ interp = (offset - off0) / (off1 - off0);
+ for (j = 0; j < n_ch; j++)
+ {
+ int z0, z1;
+ int z;
+ z0 = stops[ix - 1].color[j];
+ z1 = stops[ix].color[j];
+ z = floor (z0 + (z1 - z0) * interp + 0.5);
+ if (render->buf_depth == 8)
+ dst[j] = ART_PIX_8_FROM_MAX (z);
+ else /* (render->buf_depth == 16) */
+ ((art_u16 *)dst)[j] = z;
+ }
+ return;
+ }
+ }
+ else if (ix == n_stops)
+ ix--;
+
+ for (j = 0; j < n_ch; j++)
+ {
+ int z;
+ z = stops[ix].color[j];
+ if (render->buf_depth == 8)
+ dst[j] = ART_PIX_8_FROM_MAX (z);
+ else /* (render->buf_depth == 16) */
+ ((art_u16 *)dst)[j] = z;
+ }
+}
+
+static void
+art_render_gradient_linear_done (ArtRenderCallback *self, ArtRender *render)
+{
+ art_free (self);
+}
+
+static void
+art_render_gradient_linear_render (ArtRenderCallback *self, ArtRender *render,
+ art_u8 *dest, int y)
+{
+ ArtImageSourceGradLin *z = (ArtImageSourceGradLin *)self;
+ const ArtGradientLinear *gradient = &(z->gradient);
+ int pixstride = (render->n_chan + 1) * (render->depth >> 3);
+ int x;
+ int width = render->x1 - render->x0;
+ double offset, d_offset;
+ double actual_offset;
+ int n_stops = gradient->n_stops;
+ ArtGradientStop *stops = gradient->stops;
+ art_u8 *bufp = render->image_buf;
+ ArtGradientSpread spread = gradient->spread;
+
+ offset = render->x0 * gradient->a + y * gradient->b + gradient->c;
+ d_offset = gradient->a;
+
+ for (x = 0; x < width; x++)
+ {
+ if (spread == ART_GRADIENT_PAD)
+ actual_offset = offset;
+ else if (spread == ART_GRADIENT_REPEAT)
+ actual_offset = offset - floor (offset);
+ else /* (spread == ART_GRADIENT_REFLECT) */
+ {
+ double tmp;
+
+ tmp = offset - 2 * floor (0.5 * offset);
+ actual_offset = tmp > 1 ? 2 - tmp : tmp;
+ }
+ art_render_gradient_setpix (render, bufp, n_stops, stops, actual_offset);
+ offset += d_offset;
+ bufp += pixstride;
+ }
+}
+
+static void
+art_render_gradient_linear_negotiate (ArtImageSource *self, ArtRender *render,
+ int *p_flags,
+ int *p_buf_depth, ArtAlphaType *p_alpha)
+{
+ if (render->depth == 8 &&
+ render->n_chan == 3)
+ {
+ self->super.render = art_render_gradient_linear_render_8;
+ *p_flags = 0;
+ *p_buf_depth = 8;
+ *p_alpha = ART_ALPHA_PREMUL;
+ return;
+ }
+
+ self->super.render = art_render_gradient_linear_render;
+ *p_flags = 0;
+ *p_buf_depth = render->depth;
+ *p_alpha = ART_ALPHA_PREMUL;
+}
+
+/**
+ * art_render_gradient_linear: Add a linear gradient image source.
+ * @render: The render object.
+ * @gradient: The linear gradient.
+ *
+ * Adds the linear gradient @gradient as the image source for rendering
+ * in the render object @render.
+ **/
+void
+art_render_gradient_linear (ArtRender *render,
+ const ArtGradientLinear *gradient,
+ ArtFilterLevel level)
+{
+ ArtImageSourceGradLin *image_source = (ArtImageSourceGradLin*)art_alloc (sizeof (ArtImageSourceGradLin) +
+ sizeof (ArtGradientStop) * (gradient->n_stops - 1));
+
+ image_source->super.super.render = NULL;
+ image_source->super.super.done = art_render_gradient_linear_done;
+ image_source->super.negotiate = art_render_gradient_linear_negotiate;
+
+ /* copy the gradient into the structure */
+ image_source->gradient = *gradient;
+ image_source->gradient.stops = image_source->stops;
+ memcpy (image_source->gradient.stops, gradient->stops, sizeof (ArtGradientStop) * gradient->n_stops);
+
+ art_render_add_image_source (render, &image_source->super);
+}
+
+static void
+art_render_gradient_radial_done (ArtRenderCallback *self, ArtRender *render)
+{
+ art_free (self);
+}
+
+static void
+art_render_gradient_radial_render (ArtRenderCallback *self, ArtRender *render,
+ art_u8 *dest, int y)
+{
+ ArtImageSourceGradRad *z = (ArtImageSourceGradRad *)self;
+ const ArtGradientRadial *gradient = &(z->gradient);
+ int pixstride = (render->n_chan + 1) * (render->depth >> 3);
+ int x;
+ int x0 = render->x0;
+ int width = render->x1 - x0;
+ int n_stops = gradient->n_stops;
+ ArtGradientStop *stops = gradient->stops;
+ art_u8 *bufp = render->image_buf;
+ double fx = gradient->fx;
+ double fy = gradient->fy;
+ double dx, dy;
+ double *affine = (double*)&gradient->affine[0];
+ double aff0 = affine[0];
+ double aff1 = affine[1];
+ const double a = z->a;
+ const double arecip = 1.0 / a;
+ double b, db;
+ double c, dc, ddc;
+ double b_a, db_a;
+ double rad, drad, ddrad;
+
+ dx = x0 * aff0 + y * affine[2] + affine[4] - fx;
+ dy = x0 * aff1 + y * affine[3] + affine[5] - fy;
+ b = dx * fx + dy * fy;
+ db = aff0 * fx + aff1 * fy;
+ c = dx * dx + dy * dy;
+ dc = 2 * aff0 * dx + aff0 * aff0 + 2 * aff1 * dy + aff1 * aff1;
+ ddc = 2 * aff0 * aff0 + 2 * aff1 * aff1;
+
+ b_a = b * arecip;
+ db_a = db * arecip;
+
+ rad = b_a * b_a + c * arecip;
+ drad = 2 * b_a * db_a + db_a * db_a + dc * arecip;
+ ddrad = 2 * db_a * db_a + ddc * arecip;
+
+ for (x = 0; x < width; x++)
+ {
+ double z;
+
+ if (rad > 0)
+ z = b_a + sqrt (rad);
+ else
+ z = b_a;
+ art_render_gradient_setpix (render, bufp, n_stops, stops, z);
+ bufp += pixstride;
+ b_a += db_a;
+ rad += drad;
+ drad += ddrad;
+ }
+}
+
+static void
+art_render_gradient_radial_negotiate (ArtImageSource *self, ArtRender *render,
+ int *p_flags,
+ int *p_buf_depth, ArtAlphaType *p_alpha)
+{
+ self->super.render = art_render_gradient_radial_render;
+ *p_flags = 0;
+ *p_buf_depth = render->depth;
+ *p_alpha = ART_ALPHA_PREMUL;
+}
+
+/**
+ * art_render_gradient_radial: Add a radial gradient image source.
+ * @render: The render object.
+ * @gradient: The radial gradient.
+ *
+ * Adds the radial gradient @gradient as the image source for rendering
+ * in the render object @render.
+ **/
+void
+art_render_gradient_radial (ArtRender *render,
+ const ArtGradientRadial *gradient,
+ ArtFilterLevel level)
+{
+ ArtImageSourceGradRad *image_source = (ArtImageSourceGradRad*)art_alloc (sizeof (ArtImageSourceGradRad) +
+ sizeof (ArtGradientStop) * (gradient->n_stops - 1));
+ double fx = gradient->fx;
+ double fy = gradient->fy;
+
+ image_source->super.super.render = NULL;
+ image_source->super.super.done = art_render_gradient_radial_done;
+ image_source->super.negotiate = art_render_gradient_radial_negotiate;
+
+ /* copy the gradient into the structure */
+ image_source->gradient = *gradient;
+ image_source->gradient.stops = image_source->stops;
+ memcpy (image_source->gradient.stops, gradient->stops, sizeof (ArtGradientStop) * gradient->n_stops);
+
+ /* todo: sanitycheck fx, fy? */
+ image_source->a = 1 - fx * fx - fy * fy;
+
+ art_render_add_image_source (render, &image_source->super);
+}
diff -Nru swftools-0.9.2+ds1/lib/art/art_render_gradient.h swftools-0.9.1/lib/art/art_render_gradient.h
--- swftools-0.9.2+ds1/lib/art/art_render_gradient.h 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/art/art_render_gradient.h 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,86 @@
+/*
+ * art_render_gradient.h: Gradient image source for modular rendering.
+ *
+ * Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 2000 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Authors: Raph Levien
+ * Alexander Larsson
+ */
+
+#ifndef __ART_RENDER_GRADIENT_H__
+#define __ART_RENDER_GRADIENT_H__
+
+#ifdef LIBART_COMPILATION
+#include "art_filterlevel.h"
+#include "art_render.h"
+#else
+#include "art_filterlevel.h"
+#include "art_render.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+typedef struct _ArtGradientLinear ArtGradientLinear;
+typedef struct _ArtGradientRadial ArtGradientRadial;
+typedef struct _ArtGradientStop ArtGradientStop;
+
+typedef enum {
+ ART_GRADIENT_PAD,
+ ART_GRADIENT_REFLECT,
+ ART_GRADIENT_REPEAT
+} ArtGradientSpread;
+
+struct _ArtGradientLinear {
+ double a;
+ double b;
+ double c;
+ ArtGradientSpread spread;
+ int n_stops;
+ ArtGradientStop *stops;
+};
+
+struct _ArtGradientRadial {
+ double affine[6]; /* transforms user coordinates to unit circle */
+ double fx, fy; /* focal point in unit circle coords */
+ int n_stops;
+ ArtGradientStop *stops;
+};
+
+struct _ArtGradientStop {
+ double offset;
+ ArtPixMaxDepth color[ART_MAX_CHAN + 1];
+};
+
+void
+art_render_gradient_linear (ArtRender *render,
+ const ArtGradientLinear *gradient,
+ ArtFilterLevel level);
+
+void
+art_render_gradient_radial (ArtRender *render,
+ const ArtGradientRadial *gradient,
+ ArtFilterLevel level);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __ART_RENDER_GRADIENT_H__ */
diff -Nru swftools-0.9.2+ds1/lib/art/art_render.h swftools-0.9.1/lib/art/art_render.h
--- swftools-0.9.2+ds1/lib/art/art_render.h 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/art/art_render.h 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,181 @@
+/*
+ * art_render.h: Modular rendering architecture.
+ *
+ * Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 2000 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __ART_RENDER_H__
+#define __ART_RENDER_H__
+
+#ifdef LIBART_COMPILATION
+#include "art_alphagamma.h"
+#else
+#include "art_alphagamma.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/* Render object */
+
+#ifndef ART_MAX_DEPTH
+#define ART_MAX_DEPTH 16
+#endif
+
+#if ART_MAX_DEPTH == 16
+typedef art_u16 ArtPixMaxDepth;
+#define ART_PIX_MAX_FROM_8(x) ((x) | ((x) << 8))
+#define ART_PIX_8_FROM_MAX(x) (((x) + 0x80 - (((x) + 0x80) >> 8)) >> 8)
+#else
+#if ART_MAX_DEPTH == 8
+typedef art_u8 ArtPixMaxDepth;
+#define ART_PIX_MAX_FROM_8(x) (x)
+#define ART_PIX_8_FROM_MAX(x) (x)
+#else
+#error ART_MAX_DEPTH must be either 8 or 16
+#endif
+#endif
+
+#define ART_MAX_CHAN 16
+
+typedef struct _ArtRender ArtRender;
+typedef struct _ArtRenderCallback ArtRenderCallback;
+typedef struct _ArtRenderMaskRun ArtRenderMaskRun;
+typedef struct _ArtImageSource ArtImageSource;
+typedef struct _ArtMaskSource ArtMaskSource;
+
+typedef enum {
+ ART_ALPHA_NONE = 0,
+ ART_ALPHA_SEPARATE = 1,
+ ART_ALPHA_PREMUL = 2
+} ArtAlphaType;
+
+typedef enum {
+ ART_COMPOSITE_NORMAL,
+ ART_COMPOSITE_MULTIPLY,
+ /* todo: more */
+ ART_COMPOSITE_CUSTOM
+} ArtCompositingMode;
+
+#define ART_IMAGE_SOURCE_CAN_CLEAR 1
+#define ART_IMAGE_SOURCE_CAN_COMPOSITE 2
+
+struct _ArtRenderMaskRun {
+ int x;
+ int alpha;
+};
+
+struct _ArtRenderCallback {
+ void (*render) (ArtRenderCallback *self, ArtRender *render,
+ art_u8 *dest, int y);
+ void (*done) (ArtRenderCallback *self, ArtRender *render);
+};
+
+struct _ArtImageSource {
+ ArtRenderCallback super;
+ void (*negotiate) (ArtImageSource *self, ArtRender *render,
+ int *p_flags,
+ int *p_buf_depth, ArtAlphaType *p_alpha_type);
+};
+
+struct _ArtMaskSource {
+ ArtRenderCallback super;
+ int (*can_drive) (ArtMaskSource *self, ArtRender *render);
+ /* For each mask source, ::prepare() is invoked if it is not
+ a driver, or ::invoke_driver() if it is. */
+ void (*invoke_driver) (ArtMaskSource *self, ArtRender *render);
+ void (*prepare) (ArtMaskSource *self, ArtRender *render, art_boolean first);
+};
+
+struct _ArtRender {
+ /* parameters of destination image */
+ int x0, y0;
+ int x1, y1;
+ art_u8 *pixels;
+ int rowstride;
+ int n_chan;
+ int depth;
+ ArtAlphaType alpha_type;
+
+ art_boolean clear;
+ ArtPixMaxDepth clear_color[ART_MAX_CHAN + 1];
+ art_u32 opacity; /* [0..0x10000] */
+
+ ArtCompositingMode compositing_mode;
+
+ ArtAlphaGamma *alphagamma;
+
+ art_u8 *alpha_buf;
+
+ /* parameters of intermediate buffer */
+ int buf_depth;
+ ArtAlphaType buf_alpha;
+ art_u8 *image_buf;
+
+ /* driving alpha scanline data */
+ /* A "run" is a contiguous sequence of x values with the same alpha value. */
+ int n_run;
+ ArtRenderMaskRun *run;
+
+ /* A "span" is a contiguous sequence of x values with non-zero alpha. */
+ int n_span;
+ int *span_x;
+
+ art_boolean need_span;
+};
+
+ArtRender *
+art_render_new (int x0, int y0, int x1, int y1,
+ art_u8 *pixels, int rowstride,
+ int n_chan, int depth, ArtAlphaType alpha_type,
+ ArtAlphaGamma *alphagamma);
+
+void
+art_render_invoke (ArtRender *render);
+
+void
+art_render_clear (ArtRender *render, const ArtPixMaxDepth *clear_color);
+
+void
+art_render_clear_rgb (ArtRender *render, art_u32 clear_rgb);
+
+void
+art_render_mask_solid (ArtRender *render, int opacity);
+
+void
+art_render_image_solid (ArtRender *render, ArtPixMaxDepth *color);
+
+/* The next two functions are for custom mask sources only. */
+void
+art_render_add_mask_source (ArtRender *render, ArtMaskSource *mask_source);
+
+void
+art_render_invoke_callbacks (ArtRender *render, art_u8 *dest, int y);
+
+/* The following function is for custom image sources only. */
+void
+art_render_add_image_source (ArtRender *render, ArtImageSource *image_source);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __ART_RENDER_H__ */
+
diff -Nru swftools-0.9.2+ds1/lib/art/art_render_mask.c swftools-0.9.1/lib/art/art_render_mask.c
--- swftools-0.9.2+ds1/lib/art/art_render_mask.c 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/art/art_render_mask.c 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,168 @@
+/*
+ * art_render_mask.c: Alpha mask source for modular rendering.
+ *
+ * Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 2000 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Authors: Raph Levien
+ */
+
+#include "config.h"
+#include "art_render_mask.h"
+
+#include
+
+
+typedef struct _ArtMaskSourceMask ArtMaskSourceMask;
+
+struct _ArtMaskSourceMask {
+ ArtMaskSource super;
+ ArtRender *render;
+ art_boolean first;
+ int x0;
+ int y0;
+ int x1;
+ int y1;
+ const art_u8 *mask_buf;
+ int rowstride;
+};
+
+static void
+art_render_mask_done (ArtRenderCallback *self, ArtRender *render)
+{
+ art_free (self);
+}
+
+static int
+art_render_mask_can_drive (ArtMaskSource *self, ArtRender *render)
+{
+ return 0;
+}
+
+static void
+art_render_mask_render (ArtRenderCallback *self, ArtRender *render,
+ art_u8 *dest, int y)
+{
+ ArtMaskSourceMask *z = (ArtMaskSourceMask *)self;
+ int x0 = render->x0, x1 = render->x1;
+ int z_x0 = z->x0, z_x1 = z->x1;
+ int width = x1 - x0;
+ int z_width = z_x1 - z_x0;
+ art_u8 *alpha_buf = render->alpha_buf;
+
+ if (y < z->y0 || y >= z->y1 || z_width <= 0)
+ memset (alpha_buf, 0, width);
+ else
+ {
+ const art_u8 *src_line = z->mask_buf + (y - z->y0) * z->rowstride;
+ art_u8 *dst_line = alpha_buf + z_x0 - x0;
+
+ if (z_x0 > x0)
+ memset (alpha_buf, 0, z_x0 - x0);
+
+ if (z->first)
+ memcpy (dst_line, src_line, z_width);
+ else
+ {
+ int x;
+
+ for (x = 0; x < z_width; x++)
+ {
+ int v;
+ v = src_line[x];
+ if (v)
+ {
+ v = v * dst_line[x] + 0x80;
+ v = (v + (v >> 8)) >> 8;
+ dst_line[x] = v;
+ }
+ else
+ {
+ dst_line[x] = 0;
+ }
+ }
+ }
+
+ if (z_x1 < x1)
+ memset (alpha_buf + z_x1 - x0, 0, x1 - z_x1);
+ }
+}
+
+static void
+art_render_mask_prepare (ArtMaskSource *self, ArtRender *render,
+ art_boolean first)
+{
+ ArtMaskSourceMask *z = (ArtMaskSourceMask *)self;
+ self->super.render = art_render_mask_render;
+ z->first = first;
+}
+
+/**
+ * art_render_mask: Use an alpha buffer as a render mask source.
+ * @render: Render object.
+ * @x0: Left coordinate of mask rect.
+ * @y0: Top coordinate of mask rect.
+ * @x1: Right coordinate of mask rect.
+ * @y1: Bottom coordinate of mask rect.
+ * @mask_buf: Buffer containing 8bpp alpha mask data.
+ * @rowstride: Rowstride of @mask_buf.
+ *
+ * Adds @mask_buf to the render object as a mask. Note: @mask_buf must
+ * remain allocated until art_render_invoke() is called on @render.
+ **/
+void
+art_render_mask (ArtRender *render,
+ int x0, int y0, int x1, int y1,
+ const art_u8 *mask_buf, int rowstride)
+{
+ ArtMaskSourceMask *mask_source;
+
+ if (x0 < render->x0)
+ {
+ mask_buf += render->x0 - x0;
+ x0 = render->x0;
+ }
+ if (x1 > render->x1)
+ x1 = render->x1;
+
+ if (y0 < render->y0)
+ {
+ mask_buf += (render->y0 - y0) * rowstride;
+ y0 = render->y0;
+ }
+ if (y1 > render->y1)
+ y1 = render->y1;
+
+ mask_source = art_new (ArtMaskSourceMask, 1);
+
+ mask_source->super.super.render = NULL;
+ mask_source->super.super.done = art_render_mask_done;
+ mask_source->super.can_drive = art_render_mask_can_drive;
+ mask_source->super.invoke_driver = NULL;
+ mask_source->super.prepare = art_render_mask_prepare;
+ mask_source->render = render;
+ mask_source->x0 = x0;
+ mask_source->y0 = y0;
+ mask_source->x1 = x1;
+ mask_source->y1 = y1;
+ mask_source->mask_buf = mask_buf;
+ mask_source->rowstride = rowstride;
+
+ art_render_add_mask_source (render, &mask_source->super);
+
+}
diff -Nru swftools-0.9.2+ds1/lib/art/art_render_mask.h swftools-0.9.1/lib/art/art_render_mask.h
--- swftools-0.9.2+ds1/lib/art/art_render_mask.h 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/art/art_render_mask.h 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,47 @@
+/*
+ * art_render_mask.h: Alpha mask source for modular rendering.
+ *
+ * Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 2000 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Authors: Raph Levien
+ */
+
+#ifndef __ART_RENDER_MASK_H__
+#define __ART_RENDER_MASK_H__
+
+#ifdef LIBART_COMPILATION
+#include "art_render.h"
+#else
+#include "art_render.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+void
+art_render_mask (ArtRender *render,
+ int x0, int y0, int x1, int y1,
+ const art_u8 *mask_buf, int rowstride);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __ART_RENDER_MASK_H__ */
diff -Nru swftools-0.9.2+ds1/lib/art/art_render_svp.c swftools-0.9.1/lib/art/art_render_svp.c
--- swftools-0.9.2+ds1/lib/art/art_render_svp.c 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/art/art_render_svp.c 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,421 @@
+/*
+ * art_render_gradient.c: SVP mask source for modular rendering.
+ *
+ * Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 2000 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Authors: Raph Levien
+ */
+
+#include "art_render_svp.h"
+#include "art_svp_render_aa.h"
+
+typedef struct _ArtMaskSourceSVP ArtMaskSourceSVP;
+
+struct _ArtMaskSourceSVP {
+ ArtMaskSource super;
+ ArtRender *render;
+ const ArtSVP *svp;
+ art_u8 *dest_ptr;
+};
+
+static void
+art_render_svp_done (ArtRenderCallback *self, ArtRender *render)
+{
+ art_free (self);
+}
+
+static int
+art_render_svp_can_drive (ArtMaskSource *self, ArtRender *render)
+{
+ return 10;
+}
+
+/* The basic art_render_svp_callback function is repeated four times,
+ for all combinations of non-unit opacity and generating spans. In
+ general, I'd consider this bad style, but in this case I plead
+ a measurable performance improvement. */
+
+static void
+art_render_svp_callback (void *callback_data, int y,
+ int start, ArtSVPRenderAAStep *steps, int n_steps)
+{
+ ArtMaskSourceSVP *z = (ArtMaskSourceSVP *)callback_data;
+ ArtRender *render = z->render;
+ int n_run = 0;
+ int i;
+ int running_sum = start;
+ int x0 = render->x0;
+ int x1 = render->x1;
+ int run_x0, run_x1;
+ ArtRenderMaskRun *run = render->run;
+
+ if (n_steps > 0)
+ {
+ run_x1 = steps[0].x;
+ if (run_x1 > x0 && running_sum > 0x80ff)
+ {
+ run[0].x = x0;
+ run[0].alpha = running_sum;
+ n_run++;
+ }
+
+ for (i = 0; i < n_steps - 1; i++)
+ {
+ running_sum += steps[i].delta;
+ run_x0 = run_x1;
+ run_x1 = steps[i + 1].x;
+ if (run_x1 > run_x0)
+ {
+ run[n_run].x = run_x0;
+ run[n_run].alpha = running_sum;
+ n_run++;
+ }
+ }
+ if (x1 > run_x1)
+ {
+ running_sum += steps[n_steps - 1].delta;
+ run[n_run].x = run_x1;
+ run[n_run].alpha = running_sum;
+ n_run++;
+ }
+ if (running_sum > 0x80ff)
+ {
+ run[n_run].x = x1;
+ run[n_run].alpha = 0x8000;
+ n_run++;
+ }
+ }
+ else if ((running_sum >> 16) > 0)
+ {
+ run[0].x = x0;
+ run[0].alpha = running_sum;
+ run[1].x = x1;
+ run[1].alpha = running_sum;
+ n_run = 2;
+ }
+
+ render->n_run = n_run;
+
+ art_render_invoke_callbacks (render, z->dest_ptr, y);
+
+ z->dest_ptr += render->rowstride;
+}
+
+static void
+art_render_svp_callback_span (void *callback_data, int y,
+ int start, ArtSVPRenderAAStep *steps, int n_steps)
+{
+ ArtMaskSourceSVP *z = (ArtMaskSourceSVP *)callback_data;
+ ArtRender *render = z->render;
+ int n_run = 0;
+ int n_span = 0;
+ int i;
+ int running_sum = start;
+ int x0 = render->x0;
+ int x1 = render->x1;
+ int run_x0, run_x1;
+ ArtRenderMaskRun *run = render->run;
+ int *span_x = render->span_x;
+
+ if (n_steps > 0)
+ {
+ run_x1 = steps[0].x;
+ if (run_x1 > x0 && running_sum > 0x80ff)
+ {
+ run[0].x = x0;
+ run[0].alpha = running_sum;
+ n_run++;
+ span_x[0] = x0;
+ n_span++;
+ }
+
+ for (i = 0; i < n_steps - 1; i++)
+ {
+ running_sum += steps[i].delta;
+ run_x0 = run_x1;
+ run_x1 = steps[i + 1].x;
+ if (run_x1 > run_x0)
+ {
+ run[n_run].x = run_x0;
+ run[n_run].alpha = running_sum;
+ n_run++;
+ if ((n_span & 1) != (running_sum > 0x80ff))
+ span_x[n_span++] = run_x0;
+ }
+ }
+ if (x1 > run_x1)
+ {
+ running_sum += steps[n_steps - 1].delta;
+ run[n_run].x = run_x1;
+ run[n_run].alpha = running_sum;
+ n_run++;
+ if ((n_span & 1) != (running_sum > 0x80ff))
+ span_x[n_span++] = run_x1;
+ }
+ if (running_sum > 0x80ff)
+ {
+ run[n_run].x = x1;
+ run[n_run].alpha = 0x8000;
+ n_run++;
+ span_x[n_span++] = x1;
+ }
+ }
+ else if ((running_sum >> 16) > 0)
+ {
+ run[0].x = x0;
+ run[0].alpha = running_sum;
+ run[1].x = x1;
+ run[1].alpha = running_sum;
+ n_run = 2;
+ span_x[0] = x0;
+ span_x[1] = x1;
+ n_span = 2;
+ }
+
+ render->n_run = n_run;
+ render->n_span = n_span;
+
+ art_render_invoke_callbacks (render, z->dest_ptr, y);
+
+ z->dest_ptr += render->rowstride;
+}
+
+static void
+art_render_svp_callback_opacity (void *callback_data, int y,
+ int start, ArtSVPRenderAAStep *steps, int n_steps)
+{
+ ArtMaskSourceSVP *z = (ArtMaskSourceSVP *)callback_data;
+ ArtRender *render = z->render;
+ int n_run = 0;
+ int i;
+ art_u32 running_sum;
+ int x0 = render->x0;
+ int x1 = render->x1;
+ int run_x0, run_x1;
+ ArtRenderMaskRun *run = render->run;
+ art_u32 opacity = render->opacity;
+ art_u32 alpha;
+
+ running_sum = start - 0x7f80;
+
+ if (n_steps > 0)
+ {
+ run_x1 = steps[0].x;
+ alpha = ((running_sum >> 8) * opacity + 0x80080) >> 8;
+ if (run_x1 > x0 && alpha > 0x80ff)
+ {
+ run[0].x = x0;
+ run[0].alpha = alpha;
+ n_run++;
+ }
+
+ for (i = 0; i < n_steps - 1; i++)
+ {
+ running_sum += steps[i].delta;
+ run_x0 = run_x1;
+ run_x1 = steps[i + 1].x;
+ if (run_x1 > run_x0)
+ {
+ run[n_run].x = run_x0;
+ alpha = ((running_sum >> 8) * opacity + 0x80080) >> 8;
+ run[n_run].alpha = alpha;
+ n_run++;
+ }
+ }
+ if (x1 > run_x1)
+ {
+ running_sum += steps[n_steps - 1].delta;
+ run[n_run].x = run_x1;
+ alpha = ((running_sum >> 8) * opacity + 0x80080) >> 8;
+ run[n_run].alpha = alpha;
+ n_run++;
+ }
+ if (alpha > 0x80ff)
+ {
+ run[n_run].x = x1;
+ run[n_run].alpha = 0x8000;
+ n_run++;
+ }
+ }
+ else if ((running_sum >> 16) > 0)
+ {
+ run[0].x = x0;
+ run[0].alpha = running_sum;
+ run[1].x = x1;
+ run[1].alpha = running_sum;
+ n_run = 2;
+ }
+
+ render->n_run = n_run;
+
+ art_render_invoke_callbacks (render, z->dest_ptr, y);
+
+ z->dest_ptr += render->rowstride;
+}
+
+static void
+art_render_svp_callback_opacity_span (void *callback_data, int y,
+ int start, ArtSVPRenderAAStep *steps, int n_steps)
+{
+ ArtMaskSourceSVP *z = (ArtMaskSourceSVP *)callback_data;
+ ArtRender *render = z->render;
+ int n_run = 0;
+ int n_span = 0;
+ int i;
+ art_u32 running_sum;
+ int x0 = render->x0;
+ int x1 = render->x1;
+ int run_x0, run_x1;
+ ArtRenderMaskRun *run = render->run;
+ int *span_x = render->span_x;
+ art_u32 opacity = render->opacity;
+ art_u32 alpha;
+
+ running_sum = start - 0x7f80;
+
+ if (n_steps > 0)
+ {
+ run_x1 = steps[0].x;
+ alpha = ((running_sum >> 8) * opacity + 0x800080) >> 8;
+ if (run_x1 > x0 && alpha > 0x80ff)
+ {
+ run[0].x = x0;
+ run[0].alpha = alpha;
+ n_run++;
+ span_x[0] = x0;
+ n_span++;
+ }
+
+ for (i = 0; i < n_steps - 1; i++)
+ {
+ running_sum += steps[i].delta;
+ run_x0 = run_x1;
+ run_x1 = steps[i + 1].x;
+ if (run_x1 > run_x0)
+ {
+ run[n_run].x = run_x0;
+ alpha = ((running_sum >> 8) * opacity + 0x800080) >> 8;
+ run[n_run].alpha = alpha;
+ n_run++;
+ if ((n_span & 1) != (alpha > 0x80ff))
+ span_x[n_span++] = run_x0;
+ }
+ }
+ if (x1 > run_x1)
+ {
+ running_sum += steps[n_steps - 1].delta;
+ run[n_run].x = run_x1;
+ alpha = ((running_sum >> 8) * opacity + 0x800080) >> 8;
+ run[n_run].alpha = alpha;
+ n_run++;
+ if ((n_span & 1) != (alpha > 0x80ff))
+ span_x[n_span++] = run_x1;
+ }
+ if (alpha > 0x80ff)
+ {
+ run[n_run].x = x1;
+ run[n_run].alpha = 0x8000;
+ n_run++;
+ span_x[n_span++] = x1;
+ }
+ }
+ else if ((running_sum >> 16) > 0)
+ {
+ run[0].x = x0;
+ run[0].alpha = running_sum;
+ run[1].x = x1;
+ run[1].alpha = running_sum;
+ n_run = 2;
+ span_x[0] = x0;
+ span_x[1] = x1;
+ n_span = 2;
+ }
+
+ render->n_run = n_run;
+ render->n_span = n_span;
+
+ art_render_invoke_callbacks (render, z->dest_ptr, y);
+
+ z->dest_ptr += render->rowstride;
+}
+
+static void
+art_render_svp_invoke_driver (ArtMaskSource *self, ArtRender *render)
+{
+ ArtMaskSourceSVP *z = (ArtMaskSourceSVP *)self;
+ void (*callback) (void *callback_data,
+ int y,
+ int start,
+ ArtSVPRenderAAStep *steps, int n_steps);
+
+ z->dest_ptr = render->pixels;
+ if (render->opacity == 0x10000)
+ {
+ if (render->need_span)
+ callback = art_render_svp_callback_span;
+ else
+ callback = art_render_svp_callback;
+ }
+ else
+ {
+ if (render->need_span)
+ callback = art_render_svp_callback_opacity_span;
+ else
+ callback = art_render_svp_callback_opacity;
+ }
+
+ art_svp_render_aa (z->svp,
+ render->x0, render->y0,
+ render->x1, render->y1, callback,
+ self);
+ art_render_svp_done (&self->super, render);
+}
+
+static void
+art_render_svp_prepare (ArtMaskSource *self, ArtRender *render,
+ art_boolean first)
+{
+ /* todo */
+ art_die ("art_render_svp non-driver mode not yet implemented.\n");
+}
+
+/**
+ * art_render_svp: Use an SVP as a render mask source.
+ * @render: Render object.
+ * @svp: SVP.
+ *
+ * Adds @svp to the render object as a mask. Note: @svp must remain
+ * allocated until art_render_invoke() is called on @render.
+ **/
+void
+art_render_svp (ArtRender *render, const ArtSVP *svp)
+{
+ ArtMaskSourceSVP *mask_source;
+ mask_source = art_new (ArtMaskSourceSVP, 1);
+
+ mask_source->super.super.render = NULL;
+ mask_source->super.super.done = art_render_svp_done;
+ mask_source->super.can_drive = art_render_svp_can_drive;
+ mask_source->super.invoke_driver = art_render_svp_invoke_driver;
+ mask_source->super.prepare = art_render_svp_prepare;
+ mask_source->render = render;
+ mask_source->svp = svp;
+
+ art_render_add_mask_source (render, &mask_source->super);
+}
diff -Nru swftools-0.9.2+ds1/lib/art/art_render_svp.h swftools-0.9.1/lib/art/art_render_svp.h
--- swftools-0.9.2+ds1/lib/art/art_render_svp.h 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/art/art_render_svp.h 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,47 @@
+/*
+ * art_render_svp.h: SVP mask source for modular rendering.
+ *
+ * Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 2000 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Authors: Raph Levien
+ */
+
+#ifndef __ART_RENDER_SVP_H__
+#define __ART_RENDER_SVP_H__
+
+#ifdef LIBART_COMPILATION
+#include "art_render.h"
+#include "art_svp.h"
+#else
+#include "art_render.h"
+#include "art_svp.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+void
+art_render_svp (ArtRender *render, const ArtSVP *svp);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __ART_RENDER_SVP_H__ */
diff -Nru swftools-0.9.2+ds1/lib/art/art_rgb_a_affine.c swftools-0.9.1/lib/art/art_rgb_a_affine.c
--- swftools-0.9.2+ds1/lib/art/art_rgb_a_affine.c 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/art/art_rgb_a_affine.c 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,149 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+#include "art_rgb_a_affine.h"
+
+#include
+
+#include "art_affine.h"
+#include "art_point.h"
+#include "art_rgb_affine_private.h"
+
+/* This module handles compositing of affine-transformed alpha only images
+ over rgb pixel buffers. */
+
+/* Composite the source image over the destination image, applying the
+ affine transform. */
+
+/**
+ * art_rgb_a_affine: Affine transform source Alpha image and composite.
+ * @dst: Destination image RGB buffer.
+ * @x0: Left coordinate of destination rectangle.
+ * @y0: Top coordinate of destination rectangle.
+ * @x1: Right coordinate of destination rectangle.
+ * @y1: Bottom coordinate of destination rectangle.
+ * @dst_rowstride: Rowstride of @dst buffer.
+ * @src: Source image alpha buffer.
+ * @src_width: Width of source image.
+ * @src_height: Height of source image.
+ * @src_rowstride: Rowstride of @src buffer.
+ * @rgb: RGB foreground color, in 0xRRGGBB.
+ * @affine: Affine transform.
+ * @level: Filter level.
+ * @alphagamma: #ArtAlphaGamma for gamma-correcting the compositing.
+ *
+ * Affine transform the solid color rgb with alpha specified by the
+ * source image stored in @src, compositing over the area of destination
+ * image @dst specified by the rectangle (@x0, @y0) - (@x1, @y1).
+ * As usual in libart, the left and top edges of this rectangle are
+ * included, and the right and bottom edges are excluded.
+ *
+ * The @alphagamma parameter specifies that the alpha compositing be
+ * done in a gamma-corrected color space. In the current
+ * implementation, it is ignored.
+ *
+ * The @level parameter specifies the speed/quality tradeoff of the
+ * image interpolation. Currently, only ART_FILTER_NEAREST is
+ * implemented.
+ **/
+void
+art_rgb_a_affine (art_u8 *dst,
+ int x0, int y0, int x1, int y1, int dst_rowstride,
+ const art_u8 *src,
+ int src_width, int src_height, int src_rowstride,
+ art_u32 rgb,
+ const double affine[6],
+ ArtFilterLevel level,
+ ArtAlphaGamma *alphagamma)
+{
+ /* Note: this is a slow implementation, and is missing all filter
+ levels other than NEAREST. It is here for clarity of presentation
+ and to establish the interface. */
+ int x, y;
+ double inv[6];
+ art_u8 *dst_p, *dst_linestart;
+ const art_u8 *src_p;
+ ArtPoint pt, src_pt;
+ int src_x, src_y;
+ int alpha;
+ art_u8 bg_r, bg_g, bg_b;
+ art_u8 fg_r, fg_g, fg_b;
+ int tmp;
+ int run_x0, run_x1;
+ art_u8 r, g, b;
+
+ r = (rgb>>16)&0xff;
+ g = (rgb>>8)&0xff;
+ b = (rgb)&0xff;
+
+ dst_linestart = dst;
+ art_affine_invert (inv, affine);
+ for (y = y0; y < y1; y++)
+ {
+ pt.y = y + 0.5;
+ run_x0 = x0;
+ run_x1 = x1;
+ art_rgb_affine_run (&run_x0, &run_x1, y, src_width, src_height,
+ inv);
+ dst_p = dst_linestart + (run_x0 - x0) * 3;
+ for (x = run_x0; x < run_x1; x++)
+ {
+ pt.x = x + 0.5;
+ art_affine_point (&src_pt, &pt, inv);
+ src_x = floor (src_pt.x);
+ src_y = floor (src_pt.y);
+ src_p = src + (src_y * src_rowstride) + src_x;
+ if (src_x >= 0 && src_x < src_width &&
+ src_y >= 0 && src_y < src_height)
+ {
+
+ alpha = *src_p;
+ if (alpha)
+ {
+ if (alpha == 255)
+ {
+ dst_p[0] = r;
+ dst_p[1] = g;
+ dst_p[2] = b;
+ }
+ else
+ {
+ bg_r = dst_p[0];
+ bg_g = dst_p[1];
+ bg_b = dst_p[2];
+
+ tmp = (r - bg_r) * alpha;
+ fg_r = bg_r + ((tmp + (tmp >> 8) + 0x80) >> 8);
+ tmp = (g - bg_g) * alpha;
+ fg_g = bg_g + ((tmp + (tmp >> 8) + 0x80) >> 8);
+ tmp = (b - bg_b) * alpha;
+ fg_b = bg_b + ((tmp + (tmp >> 8) + 0x80) >> 8);
+
+ dst_p[0] = fg_r;
+ dst_p[1] = fg_g;
+ dst_p[2] = fg_b;
+ }
+ }
+ } else { dst_p[0] = 255; dst_p[1] = 0; dst_p[2] = 0; }
+ dst_p += 3;
+ }
+ dst_linestart += dst_rowstride;
+ }
+}
diff -Nru swftools-0.9.2+ds1/lib/art/art_rgb_a_affine.h swftools-0.9.1/lib/art/art_rgb_a_affine.h
--- swftools-0.9.2+ds1/lib/art/art_rgb_a_affine.h 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/art/art_rgb_a_affine.h 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,52 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __ART_RGB_A_AFFINE_H__
+#define __ART_RGB_A_AFFINE_H__
+
+/* This module handles compositing of affine-transformed alpha only images
+ over rgb pixel buffers. */
+
+#ifdef LIBART_COMPILATION
+#include "art_filterlevel.h"
+#include "art_alphagamma.h"
+#else
+#include "art_filterlevel.h"
+#include "art_alphagamma.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void
+art_rgb_a_affine (art_u8 *dst,
+ int x0, int y0, int x1, int y1, int dst_rowstride,
+ const art_u8 *src,
+ int src_width, int src_height, int src_rowstride,
+ art_u32 rgb,
+ const double affine[6],
+ ArtFilterLevel level,
+ ArtAlphaGamma *alphagamma);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff -Nru swftools-0.9.2+ds1/lib/art/art_rgba.c swftools-0.9.1/lib/art/art_rgba.c
--- swftools-0.9.2+ds1/lib/art/art_rgba.c 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/art/art_rgba.c 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,258 @@
+/*
+ * art_rgba.c: Functions for manipulating RGBA pixel data.
+ *
+ * Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 2000 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+#include "art_rgba.h"
+
+#define ART_OPTIMIZE_SPACE
+
+#ifndef ART_OPTIMIZE_SPACE
+#include "art_rgba_table.c"
+#endif
+
+/**
+ * art_rgba_rgba_composite: Composite RGBA image over RGBA buffer.
+ * @dst: Destination RGBA buffer.
+ * @src: Source RGBA buffer.
+ * @n: Number of RGBA pixels to composite.
+ *
+ * Composites the RGBA pixels in @dst over the @src buffer.
+ **/
+void
+art_rgba_rgba_composite (art_u8 *dst, const art_u8 *src, int n)
+{
+ int i;
+#ifdef WORDS_BIGENDIAN
+ art_u32 src_rgba, dst_rgba;
+#else
+ art_u32 src_abgr, dst_abgr;
+#endif
+ art_u8 src_alpha, dst_alpha;
+
+ for (i = 0; i < n; i++)
+ {
+#ifdef WORDS_BIGENDIAN
+ src_rgba = ((art_u32 *)src)[i];
+ src_alpha = src_rgba & 0xff;
+#else
+ src_abgr = ((art_u32 *)src)[i];
+ src_alpha = (src_abgr >> 24) & 0xff;
+#endif
+ if (src_alpha)
+ {
+ if (src_alpha == 0xff ||
+ (
+#ifdef WORDS_BIGENDIAN
+ dst_rgba = ((art_u32 *)dst)[i],
+ dst_alpha = dst_rgba & 0xff,
+#else
+ dst_abgr = ((art_u32 *)dst)[i],
+ dst_alpha = (dst_abgr >> 24),
+#endif
+ dst_alpha == 0))
+#ifdef WORDS_BIGENDIAN
+ ((art_u32 *)dst)[i] = src_rgba;
+#else
+ ((art_u32 *)dst)[i] = src_abgr;
+#endif
+ else
+ {
+ int r, g, b, a;
+ int src_r, src_g, src_b;
+ int dst_r, dst_g, dst_b;
+ int tmp;
+ int c;
+
+#ifdef ART_OPTIMIZE_SPACE
+ tmp = (255 - src_alpha) * (255 - dst_alpha) + 0x80;
+ a = 255 - ((tmp + (tmp >> 8)) >> 8);
+ c = ((src_alpha << 16) + (a >> 1)) / a;
+#else
+ tmp = art_rgba_composite_table[(src_alpha << 8) + dst_alpha];
+ c = tmp & 0x1ffff;
+ a = tmp >> 24;
+#endif
+#ifdef WORDS_BIGENDIAN
+ src_r = (src_rgba >> 24) & 0xff;
+ src_g = (src_rgba >> 16) & 0xff;
+ src_b = (src_rgba >> 8) & 0xff;
+ dst_r = (dst_rgba >> 24) & 0xff;
+ dst_g = (dst_rgba >> 16) & 0xff;
+ dst_b = (dst_rgba >> 8) & 0xff;
+#else
+ src_r = src_abgr & 0xff;
+ src_g = (src_abgr >> 8) & 0xff;
+ src_b = (src_abgr >> 16) & 0xff;
+ dst_r = dst_abgr & 0xff;
+ dst_g = (dst_abgr >> 8) & 0xff;
+ dst_b = (dst_abgr >> 16) & 0xff;
+#endif
+ r = dst_r + (((src_r - dst_r) * c + 0x8000) >> 16);
+ g = dst_g + (((src_g - dst_g) * c + 0x8000) >> 16);
+ b = dst_b + (((src_b - dst_b) * c + 0x8000) >> 16);
+#ifdef WORDS_BIGENDIAN
+ ((art_u32 *)dst)[i] = (r << 24) | (g << 16) | (b << 8) | a;
+#else
+ ((art_u32 *)dst)[i] = (a << 24) | (b << 16) | (g << 8) | r;
+#endif
+ }
+ }
+#if 0
+ /* it's not clear to me this optimization really wins */
+ else
+ {
+ /* skip over run of transparent pixels */
+ for (; i < n - 1; i++)
+ {
+#ifdef WORDS_BIGENDIAN
+ src_rgba = ((art_u32 *)src)[i + 1];
+ if (src_rgba & 0xff)
+ break;
+#else
+ src_abgr = ((art_u32 *)src)[i + 1];
+ if (src_abgr & 0xff000000)
+ break;
+#endif
+ }
+ }
+#endif
+ }
+}
+
+/**
+ * art_rgba_fill_run: fill an RGBA buffer a solid RGB color.
+ * @buf: Buffer to fill.
+ * @r: Red, range 0..255.
+ * @g: Green, range 0..255.
+ * @b: Blue, range 0..255.
+ * @n: Number of RGB triples to fill.
+ *
+ * Fills a buffer with @n copies of the (@r, @g, @b) triple, solid
+ * alpha. Thus, locations @buf (inclusive) through @buf + 4 * @n
+ * (exclusive) are written.
+ **/
+void
+art_rgba_fill_run (art_u8 *buf, art_u8 r, art_u8 g, art_u8 b, int n)
+{
+ int i;
+#ifdef WORDS_BIGENDIAN
+ art_u32 src_rgba;
+#else
+ art_u32 src_abgr;
+#endif
+
+#ifdef WORDS_BIGENDIAN
+ src_rgba = (r << 24) | (g << 16) | (b << 8) | 255;
+#else
+ src_abgr = (255 << 24) | (b << 16) | (g << 8) | r;
+#endif
+ for (i = 0; i < n; i++)
+ {
+#ifdef WORDS_BIGENDIAN
+ ((art_u32 *)buf)[i] = src_rgba;
+#else
+ ((art_u32 *)buf)[i] = src_abgr;
+#endif
+ }
+}
+
+/**
+ * art_rgba_run_alpha: Render semitransparent color over RGBA buffer.
+ * @buf: Buffer for rendering.
+ * @r: Red, range 0..255.
+ * @g: Green, range 0..255.
+ * @b: Blue, range 0..255.
+ * @alpha: Alpha, range 0..255.
+ * @n: Number of RGB triples to render.
+ *
+ * Renders a sequential run of solid (@r, @g, @b) color over @buf with
+ * opacity @alpha. Note that the range of @alpha is 0..255, in contrast
+ * to art_rgb_run_alpha, which has a range of 0..256.
+ **/
+void
+art_rgba_run_alpha (art_u8 *buf, art_u8 r, art_u8 g, art_u8 b, int alpha, int n)
+{
+ int i;
+#ifdef WORDS_BIGENDIAN
+ art_u32 src_rgba, dst_rgba;
+#else
+ art_u32 src_abgr, dst_abgr;
+#endif
+ art_u8 dst_alpha;
+ int a;
+ int dst_r, dst_g, dst_b;
+ int tmp;
+ int c;
+
+#ifdef WORDS_BIGENDIAN
+ src_rgba = (r << 24) | (g << 16) | (b << 8) | alpha;
+#else
+ src_abgr = (alpha << 24) | (b << 16) | (g << 8) | r;
+#endif
+ for (i = 0; i < n; i++)
+ {
+#ifdef WORDS_BIGENDIAN
+ dst_rgba = ((art_u32 *)buf)[i];
+ dst_alpha = dst_rgba & 0xff;
+#else
+ dst_abgr = ((art_u32 *)buf)[i];
+ dst_alpha = (dst_abgr >> 24) & 0xff;
+#endif
+ if (dst_alpha)
+ {
+#ifdef ART_OPTIMIZE_SPACE
+ tmp = (255 - alpha) * (255 - dst_alpha) + 0x80;
+ a = 255 - ((tmp + (tmp >> 8)) >> 8);
+ c = ((alpha << 16) + (a >> 1)) / a;
+#else
+ tmp = art_rgba_composite_table[(alpha << 8) + dst_alpha];
+ c = tmp & 0x1ffff;
+ a = tmp >> 24;
+#endif
+#ifdef WORDS_BIGENDIAN
+ dst_r = (dst_rgba >> 24) & 0xff;
+ dst_g = (dst_rgba >> 16) & 0xff;
+ dst_b = (dst_rgba >> 8) & 0xff;
+#else
+ dst_r = dst_abgr & 0xff;
+ dst_g = (dst_abgr >> 8) & 0xff;
+ dst_b = (dst_abgr >> 16) & 0xff;
+#endif
+ dst_r += (((r - dst_r) * c + 0x8000) >> 16);
+ dst_g += (((g - dst_g) * c + 0x8000) >> 16);
+ dst_b += (((b - dst_b) * c + 0x8000) >> 16);
+#ifdef WORDS_BIGENDIAN
+ ((art_u32 *)buf)[i] = (dst_r << 24) | (dst_g << 16) | (dst_b << 8) | a;
+#else
+ ((art_u32 *)buf)[i] = (a << 24) | (dst_b << 16) | (dst_g << 8) | dst_r;
+#endif
+ }
+ else
+ {
+#ifdef WORDS_BIGENDIAN
+ ((art_u32 *)buf)[i] = src_rgba;
+#else
+ ((art_u32 *)buf)[i] = src_abgr;
+#endif
+ }
+ }
+}
diff -Nru swftools-0.9.2+ds1/lib/art/art_rgb_affine.c swftools-0.9.1/lib/art/art_rgb_affine.c
--- swftools-0.9.2+ds1/lib/art/art_rgb_affine.c 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/art/art_rgb_affine.c 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,106 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+#include "art_rgb_affine.h"
+
+#include
+#include "art_misc.h"
+#include "art_point.h"
+#include "art_affine.h"
+#include "art_rgb_affine_private.h"
+
+/* This module handles compositing of affine-transformed rgb images
+ over rgb pixel buffers. */
+
+/**
+ * art_rgb_affine: Affine transform source RGB image and composite.
+ * @dst: Destination image RGB buffer.
+ * @x0: Left coordinate of destination rectangle.
+ * @y0: Top coordinate of destination rectangle.
+ * @x1: Right coordinate of destination rectangle.
+ * @y1: Bottom coordinate of destination rectangle.
+ * @dst_rowstride: Rowstride of @dst buffer.
+ * @src: Source image RGB buffer.
+ * @src_width: Width of source image.
+ * @src_height: Height of source image.
+ * @src_rowstride: Rowstride of @src buffer.
+ * @affine: Affine transform.
+ * @level: Filter level.
+ * @alphagamma: #ArtAlphaGamma for gamma-correcting the compositing.
+ *
+ * Affine transform the source image stored in @src, compositing over
+ * the area of destination image @dst specified by the rectangle
+ * (@x0, @y0) - (@x1, @y1). As usual in libart, the left and top edges
+ * of this rectangle are included, and the right and bottom edges are
+ * excluded.
+ *
+ * The @alphagamma parameter specifies that the alpha compositing be done
+ * in a gamma-corrected color space. Since the source image is opaque RGB,
+ * this argument only affects the edges. In the current implementation,
+ * it is ignored.
+ *
+ * The @level parameter specifies the speed/quality tradeoff of the
+ * image interpolation. Currently, only ART_FILTER_NEAREST is
+ * implemented.
+ **/
+void
+art_rgb_affine (art_u8 *dst, int x0, int y0, int x1, int y1, int dst_rowstride,
+ const art_u8 *src,
+ int src_width, int src_height, int src_rowstride,
+ const double affine[6],
+ ArtFilterLevel level,
+ ArtAlphaGamma *alphagamma)
+{
+ /* Note: this is a slow implementation, and is missing all filter
+ levels other than NEAREST. It is here for clarity of presentation
+ and to establish the interface. */
+ int x, y;
+ double inv[6];
+ art_u8 *dst_p, *dst_linestart;
+ const art_u8 *src_p;
+ ArtPoint pt, src_pt;
+ int src_x, src_y;
+ int run_x0, run_x1;
+
+ dst_linestart = dst;
+ art_affine_invert (inv, affine);
+ for (y = y0; y < y1; y++)
+ {
+ pt.y = y + 0.5;
+ run_x0 = x0;
+ run_x1 = x1;
+ art_rgb_affine_run (&run_x0, &run_x1, y, src_width, src_height,
+ inv);
+ dst_p = dst_linestart + (run_x0 - x0) * 3;
+ for (x = run_x0; x < run_x1; x++)
+ {
+ pt.x = x + 0.5;
+ art_affine_point (&src_pt, &pt, inv);
+ src_x = floor (src_pt.x);
+ src_y = floor (src_pt.y);
+ src_p = src + (src_y * src_rowstride) + src_x * 3;
+ dst_p[0] = src_p[0];
+ dst_p[1] = src_p[1];
+ dst_p[2] = src_p[2];
+ dst_p += 3;
+ }
+ dst_linestart += dst_rowstride;
+ }
+}
diff -Nru swftools-0.9.2+ds1/lib/art/art_rgb_affine.h swftools-0.9.1/lib/art/art_rgb_affine.h
--- swftools-0.9.2+ds1/lib/art/art_rgb_affine.h 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/art/art_rgb_affine.h 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,50 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __ART_RGB_AFFINE_H__
+#define __ART_RGB_AFFINE_H__
+
+/* This module handles compositing of affine-transformed rgb images
+ over rgb pixel buffers. */
+
+#ifdef LIBART_COMPILATION
+#include "art_filterlevel.h"
+#include "art_alphagamma.h"
+#else
+#include "art_filterlevel.h"
+#include "art_alphagamma.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void
+art_rgb_affine (art_u8 *dst, int x0, int y0, int x1, int y1, int dst_rowstride,
+ const art_u8 *src,
+ int src_width, int src_height, int src_rowstride,
+ const double affine[6],
+ ArtFilterLevel level,
+ ArtAlphaGamma *alphagamma);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff -Nru swftools-0.9.2+ds1/lib/art/art_rgb_affine_private.c swftools-0.9.1/lib/art/art_rgb_affine_private.c
--- swftools-0.9.2+ds1/lib/art/art_rgb_affine_private.c 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/art/art_rgb_affine_private.c 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,127 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+#include "art_rgb_affine_private.h"
+
+#include
+#include "art_misc.h"
+#include "art_point.h"
+#include "art_affine.h"
+
+/* Private functions for the rgb affine image compositors - primarily,
+ the determination of runs, eliminating the need for source image
+ bbox calculation in the inner loop. */
+
+/* Determine a "run", such that the inverse affine of all pixels from
+ (x0, y) inclusive to (x1, y) exclusive fit within the bounds
+ of the source image.
+
+ Initial values of x0, x1, and result values stored in first two
+ pointer arguments.
+*/
+
+#define EPSILON 1e-6
+
+void
+art_rgb_affine_run (int *p_x0, int *p_x1, int y,
+ int src_width, int src_height,
+ const double affine[6])
+{
+ int x0, x1;
+ double z;
+ double x_intercept;
+ int xi;
+
+ x0 = *p_x0;
+ x1 = *p_x1;
+
+ /* do left and right edges */
+ if (affine[0] > EPSILON)
+ {
+ z = affine[2] * (y + 0.5) + affine[4];
+ x_intercept = -z / affine[0];
+ xi = ceil (x_intercept + EPSILON - 0.5);
+ if (xi > x0)
+ x0 = xi;
+ x_intercept = (-z + src_width) / affine[0];
+ xi = ceil (x_intercept - EPSILON - 0.5);
+ if (xi < x1)
+ x1 = xi;
+ }
+ else if (affine[0] < -EPSILON)
+ {
+ z = affine[2] * (y + 0.5) + affine[4];
+ x_intercept = (-z + src_width) / affine[0];
+ xi = ceil (x_intercept + EPSILON - 0.5);
+ if (xi > x0)
+ x0 = xi;
+ x_intercept = -z / affine[0];
+ xi = ceil (x_intercept - EPSILON - 0.5);
+ if (xi < x1)
+ x1 = xi;
+ }
+ else
+ {
+ z = affine[2] * (y + 0.5) + affine[4];
+ if (z < 0 || z >= src_width)
+ {
+ *p_x1 = *p_x0;
+ return;
+ }
+ }
+
+ /* do top and bottom edges */
+ if (affine[1] > EPSILON)
+ {
+ z = affine[3] * (y + 0.5) + affine[5];
+ x_intercept = -z / affine[1];
+ xi = ceil (x_intercept + EPSILON - 0.5);
+ if (xi > x0)
+ x0 = xi;
+ x_intercept = (-z + src_height) / affine[1];
+ xi = ceil (x_intercept - EPSILON - 0.5);
+ if (xi < x1)
+ x1 = xi;
+ }
+ else if (affine[1] < -EPSILON)
+ {
+ z = affine[3] * (y + 0.5) + affine[5];
+ x_intercept = (-z + src_height) / affine[1];
+ xi = ceil (x_intercept + EPSILON - 0.5);
+ if (xi > x0)
+ x0 = xi;
+ x_intercept = -z / affine[1];
+ xi = ceil (x_intercept - EPSILON - 0.5);
+ if (xi < x1)
+ x1 = xi;
+ }
+ else
+ {
+ z = affine[3] * (y + 0.5) + affine[5];
+ if (z < 0 || z >= src_height)
+ {
+ *p_x1 = *p_x0;
+ return;
+ }
+ }
+
+ *p_x0 = x0;
+ *p_x1 = x1;
+}
diff -Nru swftools-0.9.2+ds1/lib/art/art_rgb_affine_private.h swftools-0.9.1/lib/art/art_rgb_affine_private.h
--- swftools-0.9.2+ds1/lib/art/art_rgb_affine_private.h 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/art/art_rgb_affine_private.h 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,39 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __ART_RGB_AFFINE_PRIVATE_H__
+#define __ART_RGB_AFFINE_PRIVATE_H__
+
+/* This module handles compositing of affine-transformed rgb images
+ over rgb pixel buffers. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void
+art_rgb_affine_run (int *p_x0, int *p_x1, int y,
+ int src_width, int src_height,
+ const double affine[6]);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff -Nru swftools-0.9.2+ds1/lib/art/art_rgba.h swftools-0.9.1/lib/art/art_rgba.h
--- swftools-0.9.2+ds1/lib/art/art_rgba.h 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/art/art_rgba.h 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,49 @@
+/*
+ * art_rgba.h: Functions for manipulating RGBA pixel data.
+ *
+ * Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 2000 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __ART_RGBA_H__
+#define __ART_RGBA_H__
+
+#ifdef LIBART_COMPILATION
+#include "art_misc.h"
+#else
+#include "art_misc.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+void
+art_rgba_rgba_composite (art_u8 *dst, const art_u8 *src, int n);
+
+void
+art_rgba_fill_run (art_u8 *buf, art_u8 r, art_u8 g, art_u8 b, int n);
+
+void
+art_rgba_run_alpha (art_u8 *buf, art_u8 r, art_u8 g, art_u8 b, int alpha, int n);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif
diff -Nru swftools-0.9.2+ds1/lib/art/art_rgb_bitmap_affine.c swftools-0.9.1/lib/art/art_rgb_bitmap_affine.c
--- swftools-0.9.2+ds1/lib/art/art_rgb_bitmap_affine.c 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/art/art_rgb_bitmap_affine.c 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,198 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+#include "art_rgb_bitmap_affine.h"
+
+#include
+#include "art_misc.h"
+#include "art_point.h"
+#include "art_affine.h"
+#include "art_rgb_affine_private.h"
+
+/* This module handles compositing of affine-transformed bitmap images
+ over rgb pixel buffers. */
+
+/* Composite the source image over the destination image, applying the
+ affine transform. Foreground color is given and assumed to be
+ opaque, background color is assumed to be fully transparent. */
+
+static void
+art_rgb_bitmap_affine_opaque (art_u8 *dst,
+ int x0, int y0, int x1, int y1,
+ int dst_rowstride,
+ const art_u8 *src,
+ int src_width, int src_height, int src_rowstride,
+ art_u32 rgb,
+ const double affine[6],
+ ArtFilterLevel level,
+ ArtAlphaGamma *alphagamma)
+{
+ /* Note: this is a slow implementation, and is missing all filter
+ levels other than NEAREST. It is here for clarity of presentation
+ and to establish the interface. */
+ int x, y;
+ double inv[6];
+ art_u8 *dst_p, *dst_linestart;
+ const art_u8 *src_p;
+ ArtPoint pt, src_pt;
+ int src_x, src_y;
+ art_u8 r, g, b;
+ int run_x0, run_x1;
+
+ r = rgb >> 16;
+ g = (rgb >> 8) & 0xff;
+ b = rgb & 0xff;
+ dst_linestart = dst;
+ art_affine_invert (inv, affine);
+ for (y = y0; y < y1; y++)
+ {
+ pt.y = y + 0.5;
+ run_x0 = x0;
+ run_x1 = x1;
+ art_rgb_affine_run (&run_x0, &run_x1, y, src_width, src_height,
+ inv);
+ dst_p = dst_linestart + (run_x0 - x0) * 3;
+ for (x = run_x0; x < run_x1; x++)
+ {
+ pt.x = x + 0.5;
+ art_affine_point (&src_pt, &pt, inv);
+ src_x = floor (src_pt.x);
+ src_y = floor (src_pt.y);
+ src_p = src + (src_y * src_rowstride) + (src_x >> 3);
+ if (*src_p & (128 >> (src_x & 7)))
+ {
+ dst_p[0] = r;
+ dst_p[1] = g;
+ dst_p[2] = b;
+ }
+ dst_p += 3;
+ }
+ dst_linestart += dst_rowstride;
+ }
+}
+/* Composite the source image over the destination image, applying the
+ affine transform. Foreground color is given, background color is
+ assumed to be fully transparent. */
+
+/**
+ * art_rgb_bitmap_affine: Affine transform source bitmap image and composite.
+ * @dst: Destination image RGB buffer.
+ * @x0: Left coordinate of destination rectangle.
+ * @y0: Top coordinate of destination rectangle.
+ * @x1: Right coordinate of destination rectangle.
+ * @y1: Bottom coordinate of destination rectangle.
+ * @dst_rowstride: Rowstride of @dst buffer.
+ * @src: Source image bitmap buffer.
+ * @src_width: Width of source image.
+ * @src_height: Height of source image.
+ * @src_rowstride: Rowstride of @src buffer.
+ * @rgba: RGBA foreground color, in 0xRRGGBBAA.
+ * @affine: Affine transform.
+ * @level: Filter level.
+ * @alphagamma: #ArtAlphaGamma for gamma-correcting the compositing.
+ *
+ * Affine transform the source image stored in @src, compositing over
+ * the area of destination image @dst specified by the rectangle
+ * (@x0, @y0) - (@x1, @y1).
+ *
+ * The source bitmap stored with MSB as the leftmost pixel. Source 1
+ * bits correspond to the semitransparent color @rgba, while source 0
+ * bits are transparent.
+ *
+ * See art_rgb_affine() for a description of additional parameters.
+ **/
+void
+art_rgb_bitmap_affine (art_u8 *dst,
+ int x0, int y0, int x1, int y1, int dst_rowstride,
+ const art_u8 *src,
+ int src_width, int src_height, int src_rowstride,
+ art_u32 rgba,
+ const double affine[6],
+ ArtFilterLevel level,
+ ArtAlphaGamma *alphagamma)
+{
+ /* Note: this is a slow implementation, and is missing all filter
+ levels other than NEAREST. It is here for clarity of presentation
+ and to establish the interface. */
+ int x, y;
+ double inv[6];
+ art_u8 *dst_p, *dst_linestart;
+ const art_u8 *src_p;
+ ArtPoint pt, src_pt;
+ int src_x, src_y;
+ int alpha;
+ art_u8 bg_r, bg_g, bg_b;
+ art_u8 fg_r, fg_g, fg_b;
+ art_u8 r, g, b;
+ int run_x0, run_x1;
+
+ alpha = rgba & 0xff;
+ if (alpha == 0xff)
+ {
+ art_rgb_bitmap_affine_opaque (dst, x0, y0, x1, y1, dst_rowstride,
+ src,
+ src_width, src_height, src_rowstride,
+ rgba >> 8,
+ affine,
+ level,
+ alphagamma);
+ return;
+ }
+ /* alpha = (65536 * alpha) / 255; */
+ alpha = (alpha << 8) + alpha + (alpha >> 7);
+ r = rgba >> 24;
+ g = (rgba >> 16) & 0xff;
+ b = (rgba >> 8) & 0xff;
+ dst_linestart = dst;
+ art_affine_invert (inv, affine);
+ for (y = y0; y < y1; y++)
+ {
+ pt.y = y + 0.5;
+ run_x0 = x0;
+ run_x1 = x1;
+ art_rgb_affine_run (&run_x0, &run_x1, y, src_width, src_height,
+ inv);
+ dst_p = dst_linestart + (run_x0 - x0) * 3;
+ for (x = run_x0; x < run_x1; x++)
+ {
+ pt.x = x + 0.5;
+ art_affine_point (&src_pt, &pt, inv);
+ src_x = floor (src_pt.x);
+ src_y = floor (src_pt.y);
+ src_p = src + (src_y * src_rowstride) + (src_x >> 3);
+ if (*src_p & (128 >> (src_x & 7)))
+ {
+ bg_r = dst_p[0];
+ bg_g = dst_p[1];
+ bg_b = dst_p[2];
+
+ fg_r = bg_r + (((r - bg_r) * alpha + 0x8000) >> 16);
+ fg_g = bg_g + (((g - bg_g) * alpha + 0x8000) >> 16);
+ fg_b = bg_b + (((b - bg_b) * alpha + 0x8000) >> 16);
+
+ dst_p[0] = fg_r;
+ dst_p[1] = fg_g;
+ dst_p[2] = fg_b;
+ }
+ dst_p += 3;
+ }
+ dst_linestart += dst_rowstride;
+ }
+}
diff -Nru swftools-0.9.2+ds1/lib/art/art_rgb_bitmap_affine.h swftools-0.9.1/lib/art/art_rgb_bitmap_affine.h
--- swftools-0.9.2+ds1/lib/art/art_rgb_bitmap_affine.h 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/art/art_rgb_bitmap_affine.h 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,52 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __ART_RGB_BITMAP_AFFINE_H__
+#define __ART_RGB_BITMAP_AFFINE_H__
+
+/* This module handles compositing of affine-transformed bitmap images
+ over rgb pixel buffers. */
+
+#ifdef LIBART_COMPILATION
+#include "art_filterlevel.h"
+#include "art_alphagamma.h"
+#else
+#include "art_filterlevel.h"
+#include "art_alphagamma.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void
+art_rgb_bitmap_affine (art_u8 *dst,
+ int x0, int y0, int x1, int y1, int dst_rowstride,
+ const art_u8 *src,
+ int src_width, int src_height, int src_rowstride,
+ art_u32 rgba,
+ const double affine[6],
+ ArtFilterLevel level,
+ ArtAlphaGamma *alphagamma);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff -Nru swftools-0.9.2+ds1/lib/art/art_rgb.c swftools-0.9.1/lib/art/art_rgb.c
--- swftools-0.9.2+ds1/lib/art/art_rgb.c 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/art/art_rgb.c 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,175 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+#include "art_rgb.h"
+
+#include /* for memset */
+
+/* Basic operators for manipulating 24-bit packed RGB buffers. */
+
+#define COLOR_RUN_COMPLEX
+
+#ifdef COLOR_RUN_SIMPLE
+/* This is really slow. Is there any way we might speed it up?
+ Two ideas:
+
+ First, maybe we should be working at 32-bit alignment. Then,
+ this can be a simple loop over word stores.
+
+ Second, we can keep working at 24-bit alignment, but have some
+ intelligence about storing. For example, we can iterate over
+ 4-pixel chunks (aligned at 4 pixels), with an inner loop
+ something like:
+
+ *buf++ = v1;
+ *buf++ = v2;
+ *buf++ = v3;
+
+ One source of extra complexity is the need to make sure linebuf is
+ aligned to a 32-bit boundary.
+
+ This second alternative has some complexity to it, but is
+ appealing because it really minimizes the memory bandwidth. */
+void
+art_rgb_fill_run (art_u8 *buf, art_u8 r, art_u8 g, art_u8 b, gint n)
+{
+ int i;
+
+ if (r == g && g == b)
+ {
+ memset (buf, g, n + n + n);
+ }
+ else
+ {
+ for (i = 0; i < n; i++)
+ {
+ *buf++ = r;
+ *buf++ = g;
+ *buf++ = b;
+ }
+ }
+}
+#endif
+
+#ifdef COLOR_RUN_COMPLEX
+/* This implements the second of the two ideas above. The test results
+ are _very_ encouraging - it seems the speed is within 10% of
+ memset, which is quite good! */
+/**
+ * art_rgb_fill_run: fill a buffer a solid RGB color.
+ * @buf: Buffer to fill.
+ * @r: Red, range 0..255.
+ * @g: Green, range 0..255.
+ * @b: Blue, range 0..255.
+ * @n: Number of RGB triples to fill.
+ *
+ * Fills a buffer with @n copies of the (@r, @g, @b) triple. Thus,
+ * locations @buf (inclusive) through @buf + 3 * @n (exclusive) are
+ * written.
+ *
+ * The implementation of this routine is very highly optimized.
+ **/
+void
+art_rgb_fill_run (art_u8 *buf, art_u8 r, art_u8 g, art_u8 b, int n)
+{
+ int i;
+ unsigned int v1, v2, v3;
+
+ if (r == g && g == b)
+ {
+ memset (buf, g, n + n + n);
+ }
+ else
+ {
+ if (n < 8)
+ {
+ for (i = 0; i < n; i++)
+ {
+ *buf++ = r;
+ *buf++ = g;
+ *buf++ = b;
+ }
+ } else {
+ /* handle prefix up to byte alignment */
+ /* I'm worried about this cast on sizeof(long) != sizeof(uchar *)
+ architectures, but it _should_ work. */
+ for (i = 0; ((unsigned long)buf) & 3; i++)
+ {
+ *buf++ = r;
+ *buf++ = g;
+ *buf++ = b;
+ }
+#ifndef WORDS_BIGENDIAN
+ v1 = r | (g << 8) | (b << 16) | (r << 24);
+ v3 = (v1 << 8) | b;
+ v2 = (v3 << 8) | g;
+#else
+ v1 = (r << 24) | (g << 16) | (b << 8) | r;
+ v2 = (v1 << 8) | g;
+ v3 = (v2 << 8) | b;
+#endif
+ for (; i < n - 3; i += 4)
+ {
+ ((art_u32 *)buf)[0] = v1;
+ ((art_u32 *)buf)[1] = v2;
+ ((art_u32 *)buf)[2] = v3;
+ buf += 12;
+ }
+ /* handle postfix */
+ for (; i < n; i++)
+ {
+ *buf++ = r;
+ *buf++ = g;
+ *buf++ = b;
+ }
+ }
+ }
+}
+#endif
+
+/**
+ * art_rgb_run_alpha: Render semitransparent color over RGB buffer.
+ * @buf: Buffer for rendering.
+ * @r: Red, range 0..255.
+ * @g: Green, range 0..255.
+ * @b: Blue, range 0..255.
+ * @alpha: Alpha, range 0..256.
+ * @n: Number of RGB triples to render.
+ *
+ * Renders a sequential run of solid (@r, @g, @b) color over @buf with
+ * opacity @alpha.
+ **/
+void
+art_rgb_run_alpha (art_u8 *buf, art_u8 r, art_u8 g, art_u8 b, int alpha, int n)
+{
+ int i;
+ int v;
+
+ for (i = 0; i < n; i++)
+ {
+ v = *buf;
+ *buf++ = v + (((r - v) * alpha + 0x80) >> 8);
+ v = *buf;
+ *buf++ = v + (((g - v) * alpha + 0x80) >> 8);
+ v = *buf;
+ *buf++ = v + (((b - v) * alpha + 0x80) >> 8);
+ }
+}
+
diff -Nru swftools-0.9.2+ds1/lib/art/art_rgb.h swftools-0.9.1/lib/art/art_rgb.h
--- swftools-0.9.2+ds1/lib/art/art_rgb.h 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/art/art_rgb.h 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,44 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __ART_RGB_H__
+#define __ART_RGB_H__
+
+#ifdef LIBART_COMPILATION
+#include "art_misc.h"
+#else
+#include "art_misc.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void
+art_rgb_fill_run (art_u8 *buf, art_u8 r, art_u8 g, art_u8 b, int n);
+
+void
+art_rgb_run_alpha (art_u8 *buf, art_u8 r, art_u8 g, art_u8 b, int alpha,
+ int n);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff -Nru swftools-0.9.2+ds1/lib/art/art_rgb_pixbuf_affine.c swftools-0.9.1/lib/art/art_rgb_pixbuf_affine.c
--- swftools-0.9.2+ds1/lib/art/art_rgb_pixbuf_affine.c 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/art/art_rgb_pixbuf_affine.c 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,104 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+#include "art_rgb_pixbuf_affine.h"
+
+#include
+#include "art_misc.h"
+#include "art_point.h"
+#include "art_affine.h"
+#include "art_pixbuf.h"
+#include "art_rgb_affine.h"
+#include "art_rgb_affine.h"
+#include "art_rgb_rgba_affine.h"
+
+/* This module handles compositing of affine-transformed generic
+ pixbuf images over rgb pixel buffers. */
+
+/* Composite the source image over the destination image, applying the
+ affine transform. */
+/**
+ * art_rgb_pixbuf_affine: Affine transform source RGB pixbuf and composite.
+ * @dst: Destination image RGB buffer.
+ * @x0: Left coordinate of destination rectangle.
+ * @y0: Top coordinate of destination rectangle.
+ * @x1: Right coordinate of destination rectangle.
+ * @y1: Bottom coordinate of destination rectangle.
+ * @dst_rowstride: Rowstride of @dst buffer.
+ * @pixbuf: source image pixbuf.
+ * @affine: Affine transform.
+ * @level: Filter level.
+ * @alphagamma: #ArtAlphaGamma for gamma-correcting the compositing.
+ *
+ * Affine transform the source image stored in @src, compositing over
+ * the area of destination image @dst specified by the rectangle
+ * (@x0, @y0) - (@x1, @y1). As usual in libart, the left and top edges
+ * of this rectangle are included, and the right and bottom edges are
+ * excluded.
+ *
+ * The @alphagamma parameter specifies that the alpha compositing be
+ * done in a gamma-corrected color space. In the current
+ * implementation, it is ignored.
+ *
+ * The @level parameter specifies the speed/quality tradeoff of the
+ * image interpolation. Currently, only ART_FILTER_NEAREST is
+ * implemented.
+ **/
+void
+art_rgb_pixbuf_affine (art_u8 *dst,
+ int x0, int y0, int x1, int y1, int dst_rowstride,
+ const ArtPixBuf *pixbuf,
+ const double affine[6],
+ ArtFilterLevel level,
+ ArtAlphaGamma *alphagamma)
+{
+ if (pixbuf->format != ART_PIX_RGB)
+ {
+ art_warn ("art_rgb_pixbuf_affine: need RGB format image\n");
+ return;
+ }
+
+ if (pixbuf->bits_per_sample != 8)
+ {
+ art_warn ("art_rgb_pixbuf_affine: need 8-bit sample data\n");
+ return;
+ }
+
+ if (pixbuf->n_channels != 3 + (pixbuf->has_alpha != 0))
+ {
+ art_warn ("art_rgb_pixbuf_affine: need 8-bit sample data\n");
+ return;
+ }
+
+ if (pixbuf->has_alpha)
+ art_rgb_rgba_affine (dst, x0, y0, x1, y1, dst_rowstride,
+ pixbuf->pixels,
+ pixbuf->width, pixbuf->height, pixbuf->rowstride,
+ affine,
+ level,
+ alphagamma);
+ else
+ art_rgb_affine (dst, x0, y0, x1, y1, dst_rowstride,
+ pixbuf->pixels,
+ pixbuf->width, pixbuf->height, pixbuf->rowstride,
+ affine,
+ level,
+ alphagamma);
+}
diff -Nru swftools-0.9.2+ds1/lib/art/art_rgb_pixbuf_affine.h swftools-0.9.1/lib/art/art_rgb_pixbuf_affine.h
--- swftools-0.9.2+ds1/lib/art/art_rgb_pixbuf_affine.h 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/art/art_rgb_pixbuf_affine.h 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,52 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __ART_RGB_PIXBUF_AFFINE_H__
+#define __ART_RGB_PIXBUF_AFFINE_H__
+
+/* This module handles compositing of affine-transformed generic
+ pixbuf images over rgb pixel buffers. */
+
+#ifdef LIBART_COMPILATION
+#include "art_filterlevel.h"
+#include "art_alphagamma.h"
+#include "art_pixbuf.h"
+#else
+#include "art_filterlevel.h"
+#include "art_alphagamma.h"
+#include "art_pixbuf.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void
+art_rgb_pixbuf_affine (art_u8 *dst,
+ int x0, int y0, int x1, int y1, int dst_rowstride,
+ const ArtPixBuf *pixbuf,
+ const double affine[6],
+ ArtFilterLevel level,
+ ArtAlphaGamma *alphagamma);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff -Nru swftools-0.9.2+ds1/lib/art/art_rgb_rgba_affine.c swftools-0.9.1/lib/art/art_rgb_rgba_affine.c
--- swftools-0.9.2+ds1/lib/art/art_rgb_rgba_affine.c 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/art/art_rgb_rgba_affine.c 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,142 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+#include "art_rgb_rgba_affine.h"
+
+#include
+#include "art_misc.h"
+#include "art_point.h"
+#include "art_affine.h"
+#include "art_rgb_affine_private.h"
+
+/* This module handles compositing of affine-transformed rgba images
+ over rgb pixel buffers. */
+
+/* Composite the source image over the destination image, applying the
+ affine transform. */
+
+/**
+ * art_rgb_rgba_affine: Affine transform source RGBA image and composite.
+ * @dst: Destination image RGB buffer.
+ * @x0: Left coordinate of destination rectangle.
+ * @y0: Top coordinate of destination rectangle.
+ * @x1: Right coordinate of destination rectangle.
+ * @y1: Bottom coordinate of destination rectangle.
+ * @dst_rowstride: Rowstride of @dst buffer.
+ * @src: Source image RGBA buffer.
+ * @src_width: Width of source image.
+ * @src_height: Height of source image.
+ * @src_rowstride: Rowstride of @src buffer.
+ * @affine: Affine transform.
+ * @level: Filter level.
+ * @alphagamma: #ArtAlphaGamma for gamma-correcting the compositing.
+ *
+ * Affine transform the source image stored in @src, compositing over
+ * the area of destination image @dst specified by the rectangle
+ * (@x0, @y0) - (@x1, @y1). As usual in libart, the left and top edges
+ * of this rectangle are included, and the right and bottom edges are
+ * excluded.
+ *
+ * The @alphagamma parameter specifies that the alpha compositing be
+ * done in a gamma-corrected color space. In the current
+ * implementation, it is ignored.
+ *
+ * The @level parameter specifies the speed/quality tradeoff of the
+ * image interpolation. Currently, only ART_FILTER_NEAREST is
+ * implemented.
+ **/
+void
+art_rgb_rgba_affine (art_u8 *dst,
+ int x0, int y0, int x1, int y1, int dst_rowstride,
+ const art_u8 *src,
+ int src_width, int src_height, int src_rowstride,
+ const double affine[6],
+ ArtFilterLevel level,
+ ArtAlphaGamma *alphagamma)
+{
+ /* Note: this is a slow implementation, and is missing all filter
+ levels other than NEAREST. It is here for clarity of presentation
+ and to establish the interface. */
+ int x, y;
+ double inv[6];
+ art_u8 *dst_p, *dst_linestart;
+ const art_u8 *src_p;
+ ArtPoint pt, src_pt;
+ int src_x, src_y;
+ int alpha;
+ art_u8 bg_r, bg_g, bg_b;
+ art_u8 fg_r, fg_g, fg_b;
+ int tmp;
+ int run_x0, run_x1;
+
+ dst_linestart = dst;
+ art_affine_invert (inv, affine);
+ for (y = y0; y < y1; y++)
+ {
+ pt.y = y + 0.5;
+ run_x0 = x0;
+ run_x1 = x1;
+ art_rgb_affine_run (&run_x0, &run_x1, y, src_width, src_height,
+ inv);
+ dst_p = dst_linestart + (run_x0 - x0) * 3;
+ for (x = run_x0; x < run_x1; x++)
+ {
+ pt.x = x + 0.5;
+ art_affine_point (&src_pt, &pt, inv);
+ src_x = floor (src_pt.x);
+ src_y = floor (src_pt.y);
+ src_p = src + (src_y * src_rowstride) + src_x * 4;
+ if (src_x >= 0 && src_x < src_width &&
+ src_y >= 0 && src_y < src_height)
+ {
+
+ alpha = src_p[3];
+ if (alpha)
+ {
+ if (alpha == 255)
+ {
+ dst_p[0] = src_p[0];
+ dst_p[1] = src_p[1];
+ dst_p[2] = src_p[2];
+ }
+ else
+ {
+ bg_r = dst_p[0];
+ bg_g = dst_p[1];
+ bg_b = dst_p[2];
+
+ tmp = (src_p[0] - bg_r) * alpha;
+ fg_r = bg_r + ((tmp + (tmp >> 8) + 0x80) >> 8);
+ tmp = (src_p[1] - bg_g) * alpha;
+ fg_g = bg_g + ((tmp + (tmp >> 8) + 0x80) >> 8);
+ tmp = (src_p[2] - bg_b) * alpha;
+ fg_b = bg_b + ((tmp + (tmp >> 8) + 0x80) >> 8);
+
+ dst_p[0] = fg_r;
+ dst_p[1] = fg_g;
+ dst_p[2] = fg_b;
+ }
+ }
+ } else { dst_p[0] = 255; dst_p[1] = 0; dst_p[2] = 0; }
+ dst_p += 3;
+ }
+ dst_linestart += dst_rowstride;
+ }
+}
diff -Nru swftools-0.9.2+ds1/lib/art/art_rgb_rgba_affine.h swftools-0.9.1/lib/art/art_rgb_rgba_affine.h
--- swftools-0.9.2+ds1/lib/art/art_rgb_rgba_affine.h 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/art/art_rgb_rgba_affine.h 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,51 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __ART_RGB_RGBA_AFFINE_H__
+#define __ART_RGB_RGBA_AFFINE_H__
+
+/* This module handles compositing of affine-transformed rgba images
+ over rgb pixel buffers. */
+
+#ifdef LIBART_COMPILATION
+#include "art_filterlevel.h"
+#include "art_alphagamma.h"
+#else
+#include "art_filterlevel.h"
+#include "art_alphagamma.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void
+art_rgb_rgba_affine (art_u8 *dst,
+ int x0, int y0, int x1, int y1, int dst_rowstride,
+ const art_u8 *src,
+ int src_width, int src_height, int src_rowstride,
+ const double affine[6],
+ ArtFilterLevel level,
+ ArtAlphaGamma *alphagamma);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff -Nru swftools-0.9.2+ds1/lib/art/art_rgb_svp.c swftools-0.9.1/lib/art/art_rgb_svp.c
--- swftools-0.9.2+ds1/lib/art/art_rgb_svp.c 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/art/art_rgb_svp.c 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,457 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/* Render a sorted vector path into an RGB buffer. */
+
+#include "config.h"
+#include "art_rgb_svp.h"
+
+#include "art_svp.h"
+#include "art_svp_render_aa.h"
+#include "art_rgb.h"
+
+typedef struct _ArtRgbSVPData ArtRgbSVPData;
+typedef struct _ArtRgbSVPAlphaData ArtRgbSVPAlphaData;
+
+struct _ArtRgbSVPData {
+ art_u32 rgbtab[256];
+ art_u8 *buf;
+ int rowstride;
+ int x0, x1;
+};
+
+struct _ArtRgbSVPAlphaData {
+ int alphatab[256];
+ art_u8 r, g, b, alpha;
+ art_u8 *buf;
+ int rowstride;
+ int x0, x1;
+};
+
+static void
+art_rgb_svp_callback (void *callback_data, int y,
+ int start, ArtSVPRenderAAStep *steps, int n_steps)
+{
+ ArtRgbSVPData *data = (ArtRgbSVPData *)callback_data;
+ art_u8 *linebuf;
+ int run_x0, run_x1;
+ art_u32 running_sum = start;
+ art_u32 rgb;
+ int x0, x1;
+ int k;
+
+ linebuf = data->buf;
+ x0 = data->x0;
+ x1 = data->x1;
+
+ if (n_steps > 0)
+ {
+ run_x1 = steps[0].x;
+ if (run_x1 > x0)
+ {
+ rgb = data->rgbtab[(running_sum >> 16) & 0xff];
+ art_rgb_fill_run (linebuf,
+ rgb >> 16, (rgb >> 8) & 0xff, rgb & 0xff,
+ run_x1 - x0);
+ }
+
+ for (k = 0; k < n_steps - 1; k++)
+ {
+ running_sum += steps[k].delta;
+ run_x0 = run_x1;
+ run_x1 = steps[k + 1].x;
+ if (run_x1 > run_x0)
+ {
+ rgb = data->rgbtab[(running_sum >> 16) & 0xff];
+ art_rgb_fill_run (linebuf + (run_x0 - x0) * 3,
+ rgb >> 16, (rgb >> 8) & 0xff, rgb & 0xff,
+ run_x1 - run_x0);
+ }
+ }
+ running_sum += steps[k].delta;
+ if (x1 > run_x1)
+ {
+ rgb = data->rgbtab[(running_sum >> 16) & 0xff];
+ art_rgb_fill_run (linebuf + (run_x1 - x0) * 3,
+ rgb >> 16, (rgb >> 8) & 0xff, rgb & 0xff,
+ x1 - run_x1);
+ }
+ }
+ else
+ {
+ rgb = data->rgbtab[(running_sum >> 16) & 0xff];
+ art_rgb_fill_run (linebuf,
+ rgb >> 16, (rgb >> 8) & 0xff, rgb & 0xff,
+ x1 - x0);
+ }
+
+ data->buf += data->rowstride;
+}
+
+/* Render the vector path into the RGB buffer. */
+
+/**
+ * art_rgb_svp_aa: Render sorted vector path into RGB buffer.
+ * @svp: The source sorted vector path.
+ * @x0: Left coordinate of destination rectangle.
+ * @y0: Top coordinate of destination rectangle.
+ * @x1: Right coordinate of destination rectangle.
+ * @y1: Bottom coordinate of destination rectangle.
+ * @fg_color: Foreground color in 0xRRGGBB format.
+ * @bg_color: Background color in 0xRRGGBB format.
+ * @buf: Destination RGB buffer.
+ * @rowstride: Rowstride of @buf buffer.
+ * @alphagamma: #ArtAlphaGamma for gamma-correcting the rendering.
+ *
+ * Renders the shape specified with @svp into the @buf RGB buffer.
+ * @x1 - @x0 specifies the width, and @y1 - @y0 specifies the height,
+ * of the rectangle rendered. The new pixels are stored starting at
+ * the first byte of @buf. Thus, the @x0 and @y0 parameters specify
+ * an offset within @svp, and may be tweaked as a way of doing
+ * integer-pixel translations without fiddling with @svp itself.
+ *
+ * The @fg_color and @bg_color arguments specify the opaque colors to
+ * be used for rendering. For pixels of entirely 0 winding-number,
+ * @bg_color is used. For pixels of entirely 1 winding number,
+ * @fg_color is used. In between, the color is interpolated based on
+ * the fraction of the pixel with a winding number of 1. If
+ * @alphagamma is NULL, then linear interpolation (in pixel counts) is
+ * the default. Otherwise, the interpolation is as specified by
+ * @alphagamma.
+ **/
+void
+art_rgb_svp_aa (const ArtSVP *svp,
+ int x0, int y0, int x1, int y1,
+ art_u32 fg_color, art_u32 bg_color,
+ art_u8 *buf, int rowstride,
+ ArtAlphaGamma *alphagamma)
+{
+ ArtRgbSVPData data;
+
+ int r_fg, g_fg, b_fg;
+ int r_bg, g_bg, b_bg;
+ int r, g, b;
+ int dr, dg, db;
+ int i;
+
+ if (alphagamma == NULL)
+ {
+ r_fg = fg_color >> 16;
+ g_fg = (fg_color >> 8) & 0xff;
+ b_fg = fg_color & 0xff;
+
+ r_bg = bg_color >> 16;
+ g_bg = (bg_color >> 8) & 0xff;
+ b_bg = bg_color & 0xff;
+
+ r = (r_bg << 16) + 0x8000;
+ g = (g_bg << 16) + 0x8000;
+ b = (b_bg << 16) + 0x8000;
+ dr = ((r_fg - r_bg) << 16) / 255;
+ dg = ((g_fg - g_bg) << 16) / 255;
+ db = ((b_fg - b_bg) << 16) / 255;
+
+ for (i = 0; i < 256; i++)
+ {
+ data.rgbtab[i] = (r & 0xff0000) | ((g & 0xff0000) >> 8) | (b >> 16);
+ r += dr;
+ g += dg;
+ b += db;
+ }
+ }
+ else
+ {
+ int *table;
+ art_u8 *invtab;
+
+ table = alphagamma->table;
+
+ r_fg = table[fg_color >> 16];
+ g_fg = table[(fg_color >> 8) & 0xff];
+ b_fg = table[fg_color & 0xff];
+
+ r_bg = table[bg_color >> 16];
+ g_bg = table[(bg_color >> 8) & 0xff];
+ b_bg = table[bg_color & 0xff];
+
+ r = (r_bg << 16) + 0x8000;
+ g = (g_bg << 16) + 0x8000;
+ b = (b_bg << 16) + 0x8000;
+ dr = ((r_fg - r_bg) << 16) / 255;
+ dg = ((g_fg - g_bg) << 16) / 255;
+ db = ((b_fg - b_bg) << 16) / 255;
+
+ invtab = alphagamma->invtable;
+ for (i = 0; i < 256; i++)
+ {
+ data.rgbtab[i] = (invtab[r >> 16] << 16) |
+ (invtab[g >> 16] << 8) |
+ invtab[b >> 16];
+ r += dr;
+ g += dg;
+ b += db;
+ }
+ }
+ data.buf = buf;
+ data.rowstride = rowstride;
+ data.x0 = x0;
+ data.x1 = x1;
+ art_svp_render_aa (svp, x0, y0, x1, y1, art_rgb_svp_callback, &data);
+}
+
+static void
+art_rgb_svp_alpha_callback (void *callback_data, int y,
+ int start, ArtSVPRenderAAStep *steps, int n_steps)
+{
+ ArtRgbSVPAlphaData *data = (ArtRgbSVPAlphaData *)callback_data;
+ art_u8 *linebuf;
+ int run_x0, run_x1;
+ art_u32 running_sum = start;
+ int x0, x1;
+ int k;
+ art_u8 r, g, b;
+ int *alphatab;
+ int alpha;
+
+ linebuf = data->buf;
+ x0 = data->x0;
+ x1 = data->x1;
+
+ r = data->r;
+ g = data->g;
+ b = data->b;
+ alphatab = data->alphatab;
+
+ if (n_steps > 0)
+ {
+ run_x1 = steps[0].x;
+ if (run_x1 > x0)
+ {
+ alpha = (running_sum >> 16) & 0xff;
+ if (alpha)
+ art_rgb_run_alpha (linebuf,
+ r, g, b, alphatab[alpha],
+ run_x1 - x0);
+ }
+
+ for (k = 0; k < n_steps - 1; k++)
+ {
+ running_sum += steps[k].delta;
+ run_x0 = run_x1;
+ run_x1 = steps[k + 1].x;
+ if (run_x1 > run_x0)
+ {
+ alpha = (running_sum >> 16) & 0xff;
+ if (alpha)
+ art_rgb_run_alpha (linebuf + (run_x0 - x0) * 3,
+ r, g, b, alphatab[alpha],
+ run_x1 - run_x0);
+ }
+ }
+ running_sum += steps[k].delta;
+ if (x1 > run_x1)
+ {
+ alpha = (running_sum >> 16) & 0xff;
+ if (alpha)
+ art_rgb_run_alpha (linebuf + (run_x1 - x0) * 3,
+ r, g, b, alphatab[alpha],
+ x1 - run_x1);
+ }
+ }
+ else
+ {
+ alpha = (running_sum >> 16) & 0xff;
+ if (alpha)
+ art_rgb_run_alpha (linebuf,
+ r, g, b, alphatab[alpha],
+ x1 - x0);
+ }
+
+ data->buf += data->rowstride;
+}
+
+static void
+art_rgb_svp_alpha_opaque_callback (void *callback_data, int y,
+ int start,
+ ArtSVPRenderAAStep *steps, int n_steps)
+{
+ ArtRgbSVPAlphaData *data = (ArtRgbSVPAlphaData *)callback_data;
+ art_u8 *linebuf;
+ int run_x0, run_x1;
+ art_u32 running_sum = start;
+ int x0, x1;
+ int k;
+ art_u8 r, g, b;
+ int *alphatab;
+ int alpha;
+
+ linebuf = data->buf;
+ x0 = data->x0;
+ x1 = data->x1;
+
+ r = data->r;
+ g = data->g;
+ b = data->b;
+ alphatab = data->alphatab;
+
+ if (n_steps > 0)
+ {
+ run_x1 = steps[0].x;
+ if (run_x1 > x0)
+ {
+ alpha = running_sum >> 16;
+ if (alpha)
+ {
+ if (alpha >= 255)
+ art_rgb_fill_run (linebuf,
+ r, g, b,
+ run_x1 - x0);
+ else
+ art_rgb_run_alpha (linebuf,
+ r, g, b, alphatab[alpha],
+ run_x1 - x0);
+ }
+ }
+
+ for (k = 0; k < n_steps - 1; k++)
+ {
+ running_sum += steps[k].delta;
+ run_x0 = run_x1;
+ run_x1 = steps[k + 1].x;
+ if (run_x1 > run_x0)
+ {
+ alpha = running_sum >> 16;
+ if (alpha)
+ {
+ if (alpha >= 255)
+ art_rgb_fill_run (linebuf + (run_x0 - x0) * 3,
+ r, g, b,
+ run_x1 - run_x0);
+ else
+ art_rgb_run_alpha (linebuf + (run_x0 - x0) * 3,
+ r, g, b, alphatab[alpha],
+ run_x1 - run_x0);
+ }
+ }
+ }
+ running_sum += steps[k].delta;
+ if (x1 > run_x1)
+ {
+ alpha = running_sum >> 16;
+ if (alpha)
+ {
+ if (alpha >= 255)
+ art_rgb_fill_run (linebuf + (run_x1 - x0) * 3,
+ r, g, b,
+ x1 - run_x1);
+ else
+ art_rgb_run_alpha (linebuf + (run_x1 - x0) * 3,
+ r, g, b, alphatab[alpha],
+ x1 - run_x1);
+ }
+ }
+ }
+ else
+ {
+ alpha = running_sum >> 16;
+ if (alpha)
+ {
+ if (alpha >= 255)
+ art_rgb_fill_run (linebuf,
+ r, g, b,
+ x1 - x0);
+ else
+ art_rgb_run_alpha (linebuf,
+ r, g, b, alphatab[alpha],
+ x1 - x0);
+ }
+ }
+
+ data->buf += data->rowstride;
+}
+
+/**
+ * art_rgb_svp_alpha: Alpha-composite sorted vector path over RGB buffer.
+ * @svp: The source sorted vector path.
+ * @x0: Left coordinate of destination rectangle.
+ * @y0: Top coordinate of destination rectangle.
+ * @x1: Right coordinate of destination rectangle.
+ * @y1: Bottom coordinate of destination rectangle.
+ * @rgba: Color in 0xRRGGBBAA format.
+ * @buf: Destination RGB buffer.
+ * @rowstride: Rowstride of @buf buffer.
+ * @alphagamma: #ArtAlphaGamma for gamma-correcting the compositing.
+ *
+ * Renders the shape specified with @svp over the @buf RGB buffer.
+ * @x1 - @x0 specifies the width, and @y1 - @y0 specifies the height,
+ * of the rectangle rendered. The new pixels are stored starting at
+ * the first byte of @buf. Thus, the @x0 and @y0 parameters specify
+ * an offset within @svp, and may be tweaked as a way of doing
+ * integer-pixel translations without fiddling with @svp itself.
+ *
+ * The @rgba argument specifies the color for the rendering. Pixels of
+ * entirely 0 winding number are left untouched. Pixels of entirely
+ * 1 winding number have the color @rgba composited over them (ie,
+ * are replaced by the red, green, blue components of @rgba if the alpha
+ * component is 0xff). Pixels of intermediate coverage are interpolated
+ * according to the rule in @alphagamma, or default to linear if
+ * @alphagamma is NULL.
+ **/
+void
+art_rgb_svp_alpha (const ArtSVP *svp,
+ int x0, int y0, int x1, int y1,
+ art_u32 rgba,
+ art_u8 *buf, int rowstride,
+ ArtAlphaGamma *alphagamma)
+{
+ ArtRgbSVPAlphaData data;
+ int r, g, b, alpha;
+ int i;
+ int a, da;
+
+ r = rgba >> 24;
+ g = (rgba >> 16) & 0xff;
+ b = (rgba >> 8) & 0xff;
+ alpha = rgba & 0xff;
+
+ data.r = r;
+ data.g = g;
+ data.b = b;
+ data.alpha = alpha;
+
+ a = 0x8000;
+ da = (alpha * 66051 + 0x80) >> 8; /* 66051 equals 2 ^ 32 / (255 * 255) */
+
+ for (i = 0; i < 256; i++)
+ {
+ data.alphatab[i] = a >> 16;
+ a += da;
+ }
+
+ data.buf = buf;
+ data.rowstride = rowstride;
+ data.x0 = x0;
+ data.x1 = x1;
+ if (alpha == 255)
+ art_svp_render_aa (svp, x0, y0, x1, y1, art_rgb_svp_alpha_opaque_callback,
+ &data);
+ else
+ art_svp_render_aa (svp, x0, y0, x1, y1, art_rgb_svp_alpha_callback, &data);
+}
+
diff -Nru swftools-0.9.2+ds1/lib/art/art_rgb_svp.h swftools-0.9.1/lib/art/art_rgb_svp.h
--- swftools-0.9.2+ds1/lib/art/art_rgb_svp.h 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/art/art_rgb_svp.h 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,55 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __ART_RGB_SVP_H__
+#define __ART_RGB_SVP_H__
+
+/* Render a sorted vector path into an RGB buffer. */
+
+#ifdef LIBART_COMPILATION
+#include "art_alphagamma.h"
+#include "art_svp.h"
+#else
+#include "art_alphagamma.h"
+#include "art_svp.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+void
+art_rgb_svp_aa (const ArtSVP *svp,
+ int x0, int y0, int x1, int y1,
+ art_u32 fg_color, art_u32 bg_color,
+ art_u8 *buf, int rowstride,
+ ArtAlphaGamma *alphagamma);
+
+void
+art_rgb_svp_alpha (const ArtSVP *svp,
+ int x0, int y0, int x1, int y1,
+ art_u32 rgba,
+ art_u8 *buf, int rowstride,
+ ArtAlphaGamma *alphagamma);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __ART_RGB_SVP_H__ */
diff -Nru swftools-0.9.2+ds1/lib/art/art_svp.c swftools-0.9.1/lib/art/art_svp.c
--- swftools-0.9.2+ds1/lib/art/art_svp.c 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/art/art_svp.c 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,152 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/* Basic constructors and operations for sorted vector paths */
+
+#include "config.h"
+#include "art_svp.h"
+
+#include "art_misc.h"
+
+/* Add a new segment. The arguments can be zero and NULL if the caller
+ would rather fill them in later.
+
+ We also realloc one auxiliary array of ints of size n_segs if
+ desired.
+*/
+/**
+ * art_svp_add_segment: Add a segment to an #ArtSVP structure.
+ * @p_vp: Pointer to where the #ArtSVP structure is stored.
+ * @pn_segs_max: Pointer to the allocated size of *@p_vp.
+ * @pn_points_max: Pointer to where auxiliary array is stored.
+ * @n_points: Number of points for new segment.
+ * @dir: Direction for new segment; 0 is up, 1 is down.
+ * @points: Points for new segment.
+ * @bbox: Bounding box for new segment.
+ *
+ * Adds a new segment to an ArtSVP structure. This routine reallocates
+ * the structure if necessary, updating *@p_vp and *@pn_segs_max as
+ * necessary.
+ *
+ * The new segment is simply added after all other segments. Thus,
+ * this routine should be called in order consistent with the #ArtSVP
+ * sorting rules.
+ *
+ * If the @bbox argument is given, it is simply stored in the new
+ * segment. Otherwise (if it is NULL), the bounding box is computed
+ * from the @points given.
+ **/
+int
+art_svp_add_segment (ArtSVP **p_vp, int *pn_segs_max,
+ int **pn_points_max,
+ int n_points, int dir, ArtPoint *points,
+ ArtDRect *bbox)
+{
+ int seg_num;
+ ArtSVP *svp;
+ ArtSVPSeg *seg;
+
+ svp = *p_vp;
+ seg_num = svp->n_segs++;
+ if (*pn_segs_max == seg_num)
+ {
+ *pn_segs_max <<= 1;
+ svp = (ArtSVP *)art_realloc (svp, sizeof(ArtSVP) +
+ (*pn_segs_max - 1) * sizeof(ArtSVPSeg));
+ *p_vp = svp;
+ if (pn_points_max != NULL)
+ *pn_points_max = art_renew (*pn_points_max, int, *pn_segs_max);
+ }
+ seg = &svp->segs[seg_num];
+ seg->n_points = n_points;
+ seg->dir = dir;
+ seg->points = points;
+ if (bbox)
+ seg->bbox = *bbox;
+ else if (points)
+ {
+ double x_min, x_max;
+ int i;
+
+ x_min = x_max = points[0].x;
+ for (i = 1; i < n_points; i++)
+ {
+ if (x_min > points[i].x)
+ x_min = points[i].x;
+ if (x_max < points[i].x)
+ x_max = points[i].x;
+ }
+ seg->bbox.x0 = x_min;
+ seg->bbox.y0 = points[0].y;
+
+ seg->bbox.x1 = x_max;
+ seg->bbox.y1 = points[n_points - 1].y;
+ }
+ return seg_num;
+}
+
+
+/**
+ * art_svp_free: Free an #ArtSVP structure.
+ * @svp: #ArtSVP to free.
+ *
+ * Frees an #ArtSVP structure and all the segments in it.
+ **/
+void
+art_svp_free (ArtSVP *svp)
+{
+ int n_segs = svp->n_segs;
+ int i;
+
+ for (i = 0; i < n_segs; i++)
+ art_free (svp->segs[i].points);
+ art_free (svp);
+}
+
+#ifdef ART_USE_NEW_INTERSECTOR
+#define EPSILON 0
+#else
+#define EPSILON 1e-6
+#endif
+
+/**
+ * art_svp_seg_compare: Compare two segments of an svp.
+ * @seg1: First segment to compare.
+ * @seg2: Second segment to compare.
+ *
+ * Compares two segments of an svp. Return 1 if @seg2 is below or to the
+ * right of @seg1, -1 otherwise.
+ **/
+int
+art_svp_seg_compare (const void *s1, const void *s2)
+{
+ const ArtSVPSeg *seg1 = (ArtSVPSeg *)s1;
+ const ArtSVPSeg *seg2 = (ArtSVPSeg *)s2;
+
+ if (seg1->points[0].y - EPSILON > seg2->points[0].y) return 1;
+ else if (seg1->points[0].y + EPSILON < seg2->points[0].y) return -1;
+ else if (seg1->points[0].x - EPSILON > seg2->points[0].x) return 1;
+ else if (seg1->points[0].x + EPSILON < seg2->points[0].x) return -1;
+ else if ((seg1->points[1].x - seg1->points[0].x) *
+ (seg2->points[1].y - seg2->points[0].y) -
+ (seg1->points[1].y - seg1->points[0].y) *
+ (seg2->points[1].x - seg2->points[0].x) > 0) return 1;
+ else return -1;
+}
+
diff -Nru swftools-0.9.2+ds1/lib/art/art_svp.h swftools-0.9.1/lib/art/art_svp.h
--- swftools-0.9.2+ds1/lib/art/art_svp.h 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/art/art_svp.h 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,68 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __ART_SVP_H__
+#define __ART_SVP_H__
+
+/* Basic data structures and constructors for sorted vector paths */
+
+#ifdef LIBART_COMPILATION
+#include "art_rect.h"
+#include "art_point.h"
+#else
+#include "art_rect.h"
+#include "art_point.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+typedef struct _ArtSVP ArtSVP;
+typedef struct _ArtSVPSeg ArtSVPSeg;
+
+struct _ArtSVPSeg {
+ int n_points;
+ int dir; /* == 0 for "up", 1 for "down" */
+ ArtDRect bbox;
+ ArtPoint *points;
+};
+
+struct _ArtSVP {
+ int n_segs;
+ ArtSVPSeg segs[1];
+};
+
+int
+art_svp_add_segment (ArtSVP **p_vp, int *pn_segs_max,
+ int **pn_points_max,
+ int n_points, int dir, ArtPoint *points,
+ ArtDRect *bbox);
+
+void
+art_svp_free (ArtSVP *svp);
+
+int
+art_svp_seg_compare (const void *s1, const void *s2);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __ART_SVP_H__ */
diff -Nru swftools-0.9.2+ds1/lib/art/art_svp_intersect.c swftools-0.9.1/lib/art/art_svp_intersect.c
--- swftools-0.9.2+ds1/lib/art/art_svp_intersect.c 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/art/art_svp_intersect.c 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,2195 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 2001 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/* This file contains a testbed implementation of the new intersection
+ code.
+*/
+
+#include
+#include
+#include "config.h"
+#include "art_svp_intersect.h"
+
+#include /* for sqrt */
+
+/* Sanitychecking verifies the main invariant on every priority queue
+ point. Do not use in production, as it slows things down way too
+ much. */
+#define noSANITYCHECK
+
+/* This can be used in production, to prevent hangs. Eventually, it
+ should not be necessary. */
+#define CHEAP_SANITYCHECK
+
+#define noVERBOSE
+
+#define noABORT_ON_ERROR
+
+#include "art_misc.h"
+
+/* A priority queue - perhaps move to a separate file if it becomes
+ needed somewhere else */
+
+#define ART_PRIQ_USE_HEAP
+
+typedef struct _ArtPriQ ArtPriQ;
+typedef struct _ArtPriPoint ArtPriPoint;
+
+struct _ArtPriQ {
+ int n_items;
+ int n_items_max;
+ ArtPriPoint **items;
+};
+
+struct _ArtPriPoint {
+ double x;
+ double y;
+ void *user_data;
+};
+
+static ArtPriQ *
+art_pri_new (void)
+{
+ ArtPriQ *result = art_new (ArtPriQ, 1);
+
+ result->n_items = 0;
+ result->n_items_max = 16;
+ result->items = art_new (ArtPriPoint *, result->n_items_max);
+ return result;
+}
+
+static void
+art_pri_free (ArtPriQ *pq)
+{
+ art_free (pq->items);
+ art_free (pq);
+}
+
+static art_boolean
+art_pri_empty (ArtPriQ *pq)
+{
+ return pq->n_items == 0;
+}
+
+/* This heap implementation is based on Vasek Chvatal's course notes:
+ http://www.cs.rutgers.edu/~chvatal/notes/pq.html#heap */
+
+static void
+art_pri_bubble_up (ArtPriQ *pq, int vacant, ArtPriPoint *missing)
+{
+ ArtPriPoint **items = pq->items;
+ int parent;
+
+ parent = (vacant - 1) >> 1;
+ while (vacant > 0 && (missing->y < items[parent]->y ||
+ (missing->y == items[parent]->y &&
+ missing->x < items[parent]->x)))
+ {
+ items[vacant] = items[parent];
+ vacant = parent;
+ parent = (vacant - 1) >> 1;
+ }
+
+ items[vacant] = missing;
+}
+
+static void
+art_pri_insert (ArtPriQ *pq, ArtPriPoint *point)
+{
+#ifdef VERBOSE
+ art_dprint("insert into pq %08x: %.16f,%.16f %08x\n", pq, point->x, point->y, point->user_data);
+#endif
+ if (pq->n_items == pq->n_items_max)
+ art_expand (pq->items, ArtPriPoint *, pq->n_items_max);
+
+ art_pri_bubble_up (pq, pq->n_items++, point);
+}
+
+static void
+art_pri_sift_down_from_root (ArtPriQ *pq, ArtPriPoint *missing)
+{
+ ArtPriPoint **items = pq->items;
+ int vacant = 0, child = 2;
+ int n = pq->n_items;
+
+ while (child < n)
+ {
+ if (items[child - 1]->y < items[child]->y ||
+ (items[child - 1]->y == items[child]->y &&
+ items[child - 1]->x < items[child]->x))
+ child--;
+ items[vacant] = items[child];
+ vacant = child;
+ child = (vacant + 1) << 1;
+ }
+ if (child == n)
+ {
+ items[vacant] = items[n - 1];
+ vacant = n - 1;
+ }
+
+ art_pri_bubble_up (pq, vacant, missing);
+}
+
+static ArtPriPoint *
+art_pri_choose (ArtPriQ *pq)
+{
+ ArtPriPoint *result = pq->items[0];
+
+ art_pri_sift_down_from_root (pq, pq->items[--pq->n_items]);
+ return result;
+}
+
+/* TODO: this is *not* thread save */
+const ArtSVP* current_svp = 0;
+int art_error_in_intersector=0;
+
+void art_report_error()
+{
+ art_error_in_intersector = 1;
+#ifdef ABORT_ON_ERROR
+ if(!current_svp) {
+ fprintf(stderr, "internal error: no current polygon\n");
+ exit(1);
+ }
+ const ArtSVP*svp = current_svp;
+ FILE*fi = fopen("svp.ps", "wb");
+ int i, j;
+ fprintf(fi, "%% begin\n");
+ for (i = 0; i < svp->n_segs; i++)
+ {
+ fprintf(fi, "%g setgray\n", svp->segs[i].dir ? 0.7 : 0);
+ for (j = 0; j < svp->segs[i].n_points; j++)
+ {
+ fprintf(fi, "%.32f %.32f %s\n",
+ svp->segs[i].points[j].x,
+ svp->segs[i].points[j].y,
+ j ? "lineto" : "moveto");
+ }
+ fprintf(fi, "stroke\n");
+ }
+ fprintf(fi, "showpage\n");
+ fclose(fi);
+
+ fprintf(stderr, "There was an error during polygon processing.\n");
+ fprintf(stderr, "I saved a debug file, called svp.ps, to the current directory.\n");
+ fprintf(stderr, "Please help making this tool more stable by mailing\n");
+ fprintf(stderr, "this file to debug@swftools.org. Thank you!\n");
+ exit(1);
+#endif
+}
+
+/* A virtual class for an "svp writer". A client of this object creates an
+ SVP by repeatedly calling "add segment" and "add point" methods on it.
+*/
+
+typedef struct _ArtSvpWriterRewind ArtSvpWriterRewind;
+
+/* An implementation of the svp writer virtual class that applies the
+ winding rule. */
+
+struct _ArtSvpWriterRewind {
+ ArtSvpWriter super;
+ ArtWindRule rule;
+ ArtSVP *svp;
+ int n_segs_max;
+ int *n_points_max;
+};
+
+static int
+art_svp_writer_rewind_add_segment (ArtSvpWriter *self, int wind_left,
+ int delta_wind, double x, double y)
+{
+ ArtSvpWriterRewind *swr = (ArtSvpWriterRewind *)self;
+ ArtSVP *svp;
+ ArtSVPSeg *seg;
+ art_boolean left_filled, right_filled;
+ int wind_right = wind_left + delta_wind;
+ int seg_num;
+ const int init_n_points_max = 4;
+
+ switch (swr->rule)
+ {
+ case ART_WIND_RULE_NONZERO:
+ left_filled = (wind_left != 0);
+ right_filled = (wind_right != 0);
+ break;
+ case ART_WIND_RULE_INTERSECT:
+ left_filled = (wind_left > 1);
+ right_filled = (wind_right > 1);
+ break;
+ case ART_WIND_RULE_ODDEVEN:
+ left_filled = (wind_left & 1);
+ right_filled = (wind_right & 1);
+ break;
+ case ART_WIND_RULE_POSITIVE:
+ left_filled = (wind_left > 0);
+ right_filled = (wind_right > 0);
+ break;
+ default:
+ art_die ("Unknown wind rule %d\n", swr->rule);
+ }
+
+#ifdef VERBOSE
+ art_dprint("New svp segment %d: %.32f %.32f left_filled=%d, right_filled=%d\n", swr->svp->n_segs, x, y, left_filled, right_filled);
+#endif
+
+ if (left_filled == right_filled)
+ {
+ /* discard segment now */
+#ifdef VERBOSE
+ art_dprint (" discarding segment: %d += %d (%.16f, %.16f)\n",
+ wind_left, delta_wind, x, y);
+#endif
+ return -1;
+ }
+
+ svp = swr->svp;
+ seg_num = svp->n_segs++;
+ if (swr->n_segs_max == seg_num)
+ {
+ swr->n_segs_max += 10;
+ svp = (ArtSVP *)art_realloc (svp, sizeof(ArtSVP) +
+ (swr->n_segs_max - 1) *
+ sizeof(ArtSVPSeg));
+ swr->svp = svp;
+ swr->n_points_max = art_renew (swr->n_points_max, int,
+ swr->n_segs_max);
+ }
+ seg = &svp->segs[seg_num];
+ seg->n_points = 1;
+ seg->dir = right_filled;
+ swr->n_points_max[seg_num] = init_n_points_max;
+ seg->bbox.x0 = x;
+ seg->bbox.y0 = y;
+ seg->bbox.x1 = x;
+ seg->bbox.y1 = y;
+ seg->points = art_new (ArtPoint, init_n_points_max);
+ seg->points[0].x = x;
+ seg->points[0].y = y;
+#ifdef VERBOSE
+ art_dprint ("swr add_segment: %d += %d (%.16f, %.16f) --> %d (%s)\n",
+ wind_left, delta_wind, x, y, seg_num,
+ seg->dir ? "filled" : "non-filled");
+#endif
+ return seg_num;
+}
+
+static void
+art_svp_writer_rewind_add_point (ArtSvpWriter *self, int seg_id,
+ double x, double y)
+{
+
+ ArtSvpWriterRewind *swr = (ArtSvpWriterRewind *)self;
+ ArtSVPSeg *seg;
+ int n_points;
+
+#ifdef VERBOSE
+ art_dprint ("swr add_point: %d (%.16f, %.16f)\n", seg_id, x, y);
+#endif
+ if (seg_id < 0)
+ /* omitted segment */
+ return;
+
+ seg = &swr->svp->segs[seg_id];
+
+ if(seg->n_points &&
+ seg->points[seg->n_points-1].x == x &&
+ seg->points[seg->n_points-1].y == y) {
+ //art_warn("duplicate point %.16f,%.16f in segment %08x\n",
+ // x, y, seg_id);
+ return;
+ }
+
+ n_points = seg->n_points++;
+ if (swr->n_points_max[seg_id] == n_points)
+ art_expand (seg->points, ArtPoint, swr->n_points_max[seg_id]);
+
+ if(0 && n_points>=2) {
+ double dx1 = seg->points[n_points-1].x - seg->points[n_points-2].x;
+ double dy1 = seg->points[n_points-1].y - seg->points[n_points-2].y;
+ double dx2 = x - seg->points[n_points-2].x;
+ double dy2 = y - seg->points[n_points-2].y;
+ if(fabs(dx1*dy2 - dx2*dy1) < 1e-10) {
+ seg->n_points--;
+ n_points--; // remove previous point pointing in the same direction
+
+ //art_warn("redundant point %.16f,%.16f in segment %08x\n",
+ // seg->points[n_points-1].x, seg->points[n_points-1].y,
+ // seg_id);
+ }
+ }
+
+ if(n_points && seg->points[n_points-1].y > y) {
+ art_warn("non-increasing segment (%.16f -> %.16f)\n", seg->points[n_points-1].y, y);
+ art_report_error();
+ }
+
+ seg->points[n_points].x = x;
+ seg->points[n_points].y = y;
+ if (x < seg->bbox.x0)
+ seg->bbox.x0 = x;
+ if (x > seg->bbox.x1)
+ seg->bbox.x1 = x;
+ seg->bbox.y1 = y;
+}
+
+static void
+art_svp_writer_rewind_close_segment (ArtSvpWriter *self, int seg_id)
+{
+ /* Not needed for this simple implementation. A potential future
+ optimization is to merge segments that can be merged safely. */
+#ifdef CHEAP_SANITYCHECK
+ ArtSvpWriterRewind *swr = (ArtSvpWriterRewind *)self;
+ ArtSVPSeg *seg;
+
+ if (seg_id >= 0)
+ {
+ seg = &swr->svp->segs[seg_id];
+ if (seg->n_points < 2)
+ art_warn ("*** closing segment %d with only %d point%s\n",
+ seg_id, seg->n_points, seg->n_points == 1 ? "" : "s");
+ }
+#endif
+
+#ifdef VERBOSE
+ art_dprint ("swr close_segment: %d\n", seg_id);
+#endif
+}
+
+ArtSVP *
+art_svp_writer_rewind_reap (ArtSvpWriter *self)
+{
+ ArtSvpWriterRewind *swr = (ArtSvpWriterRewind *)self;
+ ArtSVP *result = swr->svp;
+
+ art_free (swr->n_points_max);
+ art_free (swr);
+ return result;
+}
+
+ArtSvpWriter *
+art_svp_writer_rewind_new (ArtWindRule rule)
+{
+ ArtSvpWriterRewind *result = art_new (ArtSvpWriterRewind, 1);
+
+ result->super.add_segment = art_svp_writer_rewind_add_segment;
+ result->super.add_point = art_svp_writer_rewind_add_point;
+ result->super.close_segment = art_svp_writer_rewind_close_segment;
+
+ result->rule = rule;
+ result->n_segs_max = 16;
+ result->svp = (ArtSVP*)art_alloc (sizeof(ArtSVP) +
+ (result->n_segs_max - 1) * sizeof(ArtSVPSeg));
+ result->svp->n_segs = 0;
+ result->n_points_max = (int*)art_new (int, result->n_segs_max);
+
+ return &result->super;
+}
+
+/* Now, data structures for the active list.
+
+ signs:
+ / |
+ b<0 / | \ b>0, c<0
+ c>0 /\ | /\
+ / \ | / \
+ / \ | /
+ \|/
+ -------------+--------------------
+ /|\
+ \ / | \ /
+ \/ | \/ b<0, c<0
+ b>0 \ | /
+ c>0 \ | /
+ */
+
+typedef struct _ArtActiveSeg ArtActiveSeg;
+
+/* Note: BNEG is 1 for \ lines, and 0 for /. Thus,
+ x[(flags & BNEG) ^ 1] <= x[flags & BNEG] */
+#define ART_ACTIVE_FLAGS_BNEG 1
+
+/* This flag is set if the segment has been inserted into the active
+ list. */
+#define ART_ACTIVE_FLAGS_IN_ACTIVE 2
+
+/* This flag is set when the segment is to be deleted in the
+ horiz commit process. */
+#define ART_ACTIVE_FLAGS_DEL 4
+
+/* This flag is set if the seg_id is a valid output segment. */
+#define ART_ACTIVE_FLAGS_OUT 8
+
+/* This flag is set if the segment is in the horiz list. */
+#define ART_ACTIVE_FLAGS_IN_HORIZ 16
+
+struct _ArtActiveSeg {
+ int flags;
+ int wind_left, delta_wind;
+ ArtActiveSeg *left, *right; /* doubly linked list structure */
+
+ const ArtSVPSeg *in_seg;
+ int in_curs;
+
+ double x[2];
+ double y0, y1;
+ double a, b, c; /* line equation; ax+by+c = 0 for the line, a^2 + b^2 = 1,
+ and a>0 */
+
+ /* bottom point and intersection point stack */
+ int n_stack;
+ int n_stack_max;
+ ArtPoint *stack;
+
+ /* horiz commit list */
+ ArtActiveSeg *horiz_left, *horiz_right;
+ double horiz_x;
+ int horiz_delta_wind;
+ int seg_id;
+};
+
+typedef struct _ArtIntersectCtx ArtIntersectCtx;
+
+struct _ArtIntersectCtx {
+ const ArtSVP *in;
+ ArtSvpWriter *out;
+
+ ArtPriQ *pq;
+
+ ArtActiveSeg *active_head;
+
+ double y;
+ ArtActiveSeg *horiz_first;
+ ArtActiveSeg *horiz_last;
+
+ /* segment index of next input segment to be added to pri q */
+ int in_curs;
+};
+
+#define EPSILON_A 1e-5 /* Threshold for breaking lines at point insertions */
+
+/**
+ * art_svp_intersect_setup_seg: Set up an active segment from input segment.
+ * @seg: Active segment.
+ * @pri_pt: Priority queue point to initialize.
+ *
+ * Sets the x[], a, b, c, flags, and stack fields according to the
+ * line from the current cursor value. Sets the priority queue point
+ * to the bottom point of this line. Also advances the input segment
+ * cursor.
+ **/
+static void
+art_svp_intersect_setup_seg (ArtActiveSeg *seg, ArtPriPoint *pri_pt)
+{
+ const ArtSVPSeg *in_seg = seg->in_seg;
+ int in_curs = 0;
+ double x0, y0, x1, y1;
+ double dx, dy, s;
+ double a, b, r2;
+
+ //do {
+ in_curs = seg->in_curs++;
+ //} while(in_seg->points[in_curs].x == in_seg->points[in_curs + 1].x &&
+ // in_seg->points[in_curs].y == in_seg->points[in_curs + 1].y &&
+ // in_curs < in_seg->n_points-1
+ // );
+
+ x0 = in_seg->points[in_curs].x;
+ y0 = in_seg->points[in_curs].y;
+ x1 = in_seg->points[in_curs + 1].x;
+ y1 = in_seg->points[in_curs + 1].y;
+ pri_pt->x = x1;
+ pri_pt->y = y1;
+ dx = x1 - x0;
+ dy = y1 - y0;
+ r2 = dx * dx + dy * dy;
+ if(r2 == 0) {
+ //art_warn("segment %08x has zero length\n", seg);
+ }
+ s = r2 == 0 ? 1 : 1 / sqrt (r2);
+ seg->a = a = dy * s;
+ seg->b = b = -dx * s;
+ seg->c = -(a * x0 + b * y0);
+ seg->flags = (seg->flags & ~ART_ACTIVE_FLAGS_BNEG) | (dx > 0);
+ seg->x[0] = x0;
+ seg->x[1] = x1;
+ seg->y0 = y0;
+ seg->y1 = y1;
+ seg->n_stack = 1;
+ seg->stack[0].x = x1;
+ seg->stack[0].y = y1;
+
+ if(y1 < y0) {
+ art_warn("art_svp_intersect.c: bad input polygon %08x, contains decreasing y values\n", seg->in_seg);
+ art_report_error();
+ }
+#ifdef VERBOSE
+ art_dprint("segment %08x (top: %.16f,%.16f) starts with endpoint at %.16f,%.16f\n", seg,
+ x0, y0,
+ x1, y1);
+#endif
+}
+
+/**
+ * art_svp_intersect_add_horiz: Add point to horizontal list.
+ * @ctx: Intersector context.
+ * @seg: Segment with point to insert into horizontal list.
+ *
+ * Inserts @seg into horizontal list, keeping it in ascending horiz_x
+ * order.
+ *
+ * Note: the horiz_commit routine processes "clusters" of segs in the
+ * horiz list, all sharing the same horiz_x value. The cluster is
+ * processed in active list order, rather than horiz list order. Thus,
+ * the order of segs in the horiz list sharing the same horiz_x
+ * _should_ be irrelevant. Even so, we use b as a secondary sorting key,
+ * as a "belt and suspenders" defensive coding tactic.
+ **/
+static void
+art_svp_intersect_add_horiz (ArtIntersectCtx *ctx, ArtActiveSeg *seg)
+{
+ ArtActiveSeg **pp = &ctx->horiz_last;
+ ArtActiveSeg *place;
+ ArtActiveSeg *place_right = NULL;
+
+#ifdef CHEAP_SANITYCHECK
+ if (seg->flags & ART_ACTIVE_FLAGS_IN_HORIZ)
+ {
+ double dx = seg->x[1] - seg->x[0];
+ double dy = seg->y1 - seg->y0;
+ double len = sqrt(dx*dx+dy*dy);
+ art_warn("attempt to put segment %08x %.16f,%.16f (len:%.16f) in horiz list twice\n", seg, seg->x[0], seg->y0, len);
+ return;
+ }
+ seg->flags |= ART_ACTIVE_FLAGS_IN_HORIZ;
+#endif
+
+#ifdef VERBOSE
+ art_dprint ("add_horiz %08x, x = %.16f\n", (unsigned long) seg, seg->horiz_x);
+#endif
+ for (place = *pp; place != NULL && (place->horiz_x > seg->horiz_x ||
+ (place->horiz_x == seg->horiz_x &&
+ place->b < seg->b));
+ place = *pp)
+ {
+ place_right = place;
+ pp = &place->horiz_left;
+ }
+ *pp = seg;
+ seg->horiz_left = place;
+ seg->horiz_right = place_right;
+
+ if (place == NULL)
+ ctx->horiz_first = seg;
+ else
+ place->horiz_right = seg;
+
+#ifdef VERBOSE
+ art_dprint("horiz_list:\n");
+ ArtActiveSeg*s = ctx->horiz_first;
+ while(s) {
+ art_dprint(" %08x x=%.16f wind_left=%d delta_wind=%d horiz_delta_wind=%d\n", s, s->horiz_x,
+ s->wind_left, s->delta_wind, s->horiz_delta_wind);
+ s = s->horiz_right;
+ }
+#endif
+}
+
+static void
+art_svp_intersect_push_pt (ArtIntersectCtx *ctx, ArtActiveSeg *seg,
+ double x, double y)
+{
+ ArtPriPoint *pri_pt;
+ int n_stack = seg->n_stack;
+
+ if (n_stack == seg->n_stack_max)
+ art_expand (seg->stack, ArtPoint, seg->n_stack_max);
+
+
+ seg->stack[n_stack].x = x;
+ seg->stack[n_stack].y = y;
+ seg->n_stack++;
+
+#ifdef VERBOSE
+ int t;
+ art_dprint("art_svp_intersect_push_pt %08x |top %.16f,%.16f\n", seg, seg->x[0], seg->y0);
+ for(t=seg->n_stack-1;t>=0;t--) {
+ if(t!=seg->n_stack-1)
+ art_dprint("art_svp_intersect_push_pt %08x |pt %.16f,%.16f\n", seg, seg->stack[t].x, seg->stack[t].y);
+ else
+ art_dprint("art_svp_intersect_push_pt %08x |new %.16f,%.16f\n", seg, seg->stack[t].x, seg->stack[t].y);
+ }
+#endif
+#ifdef VERBOSE
+ art_dprint("(shortening segment %08x to %.16f,%.16f)\n", seg, x, y);
+#endif
+
+ if(seg->stack[seg->n_stack-1].y == seg->y0) {
+ art_warn("duplicate y coordinate (=y0) in point stack\n");
+ }
+
+ if(n_stack) {
+ if(seg->stack[seg->n_stack-2].y < seg->stack[seg->n_stack-1].y) {
+ art_warn("bad shortening- segment got *longer*\n");
+ art_report_error();
+ }
+ }
+
+
+ seg->x[1] = x;
+ seg->y1 = y;
+
+ pri_pt = art_new (ArtPriPoint, 1);
+ pri_pt->x = x;
+ pri_pt->y = y;
+ pri_pt->user_data = seg;
+ art_pri_insert (ctx->pq, pri_pt);
+}
+
+#define ART_BREAK_LEFT 1
+#define ART_BREAK_RIGHT 2
+
+/**
+ * art_svp_intersect_break: Break an active segment.
+ *
+ * Note: y must be greater than the top point's y, and less than
+ * the bottom's.
+ *
+ * Return value: x coordinate of break point.
+ */
+static double
+art_svp_intersect_break (ArtIntersectCtx *ctx, ArtActiveSeg *seg,
+ double x_ref, double y, int break_flags)
+{
+ double x0, y0, x1, y1;
+ const ArtSVPSeg *in_seg = seg->in_seg;
+ int in_curs = seg->in_curs;
+ double x;
+
+ x0 = in_seg->points[in_curs - 1].x;
+ y0 = in_seg->points[in_curs - 1].y;
+ x1 = in_seg->points[in_curs].x;
+ y1 = in_seg->points[in_curs].y;
+
+ x = x0 + (x1 - x0) * ((y - y0) / (y1 - y0));
+
+ //printf("%d %.16f %.16f %d\n", break_flags&ART_BREAK_LEFT, x, x_ref, x > x_ref);
+ //printf("%d %.16f %.16f %d\n", break_flags&ART_BREAK_RIGHT, x, x_ref, x < x_ref);
+
+ if ((break_flags == ART_BREAK_LEFT && x > x_ref) ||
+ (break_flags == ART_BREAK_RIGHT && x < x_ref))
+ {
+#ifdef VERBOSE
+ art_dprint ("art_svp_intersect_break %08x: limiting x to %.16f, was %.16f, %s\n", seg,
+ x_ref, x, break_flags == ART_BREAK_LEFT ? "left" : "right");
+#endif
+ //x = x_ref; //used to be *within* the VERBOSE comment
+ }
+
+ if(y < y0 || y > y1) {
+ art_warn("!! bad break %.16f of %.16f-%.16f\n", y, y0, y1);
+ art_report_error();
+ return x;
+ }
+
+ /* I think we can count on min(x0, x1) <= x <= max(x0, x1) with sane
+ arithmetic, but it might be worthwhile to check just in case. */
+
+ /* TODO: should we check seg instead of in_seg ? */
+ if(x0x1) {
+ art_warn("bad x value %.16f in intersect_break: not between %.16f and %.16f\n", x, x0, x1);
+ art_report_error();
+ }
+ } else {
+ if(xx0) {
+ art_warn("bad x value %.16f in intersect_break: not between %.16f and %.16f\n", x, x1, x0);
+ art_report_error();
+ }
+ }
+
+
+ if (y > ctx->y)
+ art_svp_intersect_push_pt (ctx, seg, x, y);
+ else
+ {
+ if(y < ctx->y) {
+ art_warn("intersect_break at a y above the current scanline (%.16f < %.16f)", y, ctx->y);
+ art_report_error();
+ }
+ seg->x[0] = x;
+ seg->y0 = y;
+ seg->horiz_x = x;
+ art_svp_intersect_add_horiz (ctx, seg);
+ }
+
+ return x;
+}
+
+/**
+ * art_svp_intersect_add_point: Add a point, breaking nearby neighbors.
+ * @ctx: Intersector context.
+ * @x: X coordinate of point to add.
+ * @y: Y coordinate of point to add.
+ * @seg: "nearby" segment, or NULL if leftmost.
+ *
+ * Return value: Segment immediately to the left of the new point, or
+ * NULL if the new point is leftmost.
+ **/
+static ArtActiveSeg *
+art_svp_intersect_add_point (ArtIntersectCtx *ctx, double x, double y,
+ ArtActiveSeg *seg, int break_flags)
+{
+ ArtActiveSeg *left, *right;
+ double x_min = x, x_max = x;
+ art_boolean left_live, right_live;
+ double d;
+ double new_x;
+ ArtActiveSeg *test, *result = NULL;
+ double x_test;
+
+ left = seg;
+ if (left == NULL)
+ right = ctx->active_head;
+ else
+ right = left->right;
+ left_live = (break_flags & ART_BREAK_LEFT) && (left != NULL);
+ right_live = (break_flags & ART_BREAK_RIGHT) && (right != NULL);
+
+#ifdef VERBOSE
+ double dd = 0;
+ if(seg)
+ dd = seg->a*x + seg->b*y + seg->c;
+ art_dprint("add_point seg=%08x %f,%f%s%s (left=%08x, right=%08x) d=%f\n", seg, x, y,
+ break_flags&ART_BREAK_LEFT?" BREAK_LEFT":"",
+ break_flags&ART_BREAK_LEFT?" BREAK_RIGHT":"",
+ seg?seg->left:0, seg?seg->right:0, dd);
+#endif
+ /* add_point relies on the fact that the active list is ascending-
+ no checks are done for lines which are not in strict order.
+
+ a point position (x,y) is tested against left (if break_flags&ART_BREAK_LEFT)
+ and right (if break_flags&ART_BREAK_RIGHT) neighboring segments which are
+ within EPSILON_A distance of the point. If they are, they are split at y.
+ For ART_BREAK_LEFT, the "intersection point" on the line (which is to the left
+ of (x,y) will never be to the right of "our" (x,y)- new_x will be shifted
+ by _break to make sure of that. (Which should only happen for horizontal
+ line segments) Likewise for ART_BREAK_RIGHT.
+
+ The horizontal area around (x,y) (x_min, x_max) will be extended into the
+ break direction for every cut we make.
+ */
+
+ //new_x = art_svp_intersect_break (ctx, left, x_min, y, ART_BREAK_LEFT);
+
+ while (left_live || right_live)
+ {
+#ifdef VERBOSE
+ art_dprint(" left: %08x (%d) right: %08x (%d)\n", left, left_live, right, right_live);
+#endif
+ if (left_live)
+ {
+ if (x <= left->x[left->flags & ART_ACTIVE_FLAGS_BNEG] &&
+ /* It may be that one of these conjuncts turns out to be always
+ true. We test both anyway, to be defensive. */
+ y != left->y0 && y < left->y1)
+ {
+ d = x_min * left->a + y * left->b + left->c;
+ if (d < EPSILON_A)
+ {
+ new_x = art_svp_intersect_break (ctx, left, x_min, y,
+ ART_BREAK_LEFT);
+#ifdef VERBOSE
+ art_dprint("break %08x at x<=%.16f,y=%.16f, new_x=%f\n", left, x_min, y, new_x);
+#endif
+ if (new_x > x_max)
+ {
+ x_max = new_x;
+ right_live = (right != NULL);
+ }
+ else if (new_x < x_min)
+ x_min = new_x;
+ left = left->left;
+ left_live = (left != NULL);
+ }
+ else
+ left_live = ART_FALSE;
+ }
+ else
+ left_live = ART_FALSE;
+ }
+ else if (right_live)
+ {
+ if (x >= right->x[(right->flags & ART_ACTIVE_FLAGS_BNEG) ^ 1] &&
+ /* It may be that one of these conjuncts turns out to be always
+ true. We test both anyway, to be defensive. */
+ y != right->y0 && y < right->y1)
+ {
+ d = x_max * right->a + y * right->b + right->c;
+ if (d > -EPSILON_A)
+ {
+ new_x = art_svp_intersect_break (ctx, right, x_max, y,
+ ART_BREAK_RIGHT);
+#ifdef VERBOSE
+ art_dprint("break %08x at x>=%.16f,y=%.16f, new_x=%f\n", right, x_max, y, new_x);
+#endif
+ if (new_x < x_min)
+ {
+ x_min = new_x;
+ left_live = (left != NULL);
+ }
+ else if (new_x >= x_max)
+ x_max = new_x;
+ right = right->right;
+ right_live = (right != NULL);
+ }
+ else
+ right_live = ART_FALSE;
+ }
+ else
+ right_live = ART_FALSE;
+ }
+ }
+
+ /* Ascending order is guaranteed by break_flags. Thus, we don't need
+ to actually fix up non-ascending pairs. */
+
+ /* Now, (left, right) defines an interval of segments broken. Sort
+ into ascending x order. (find segment to the left of the new point) */
+ test = left == NULL ? ctx->active_head : left->right;
+ result = left;
+ if (test != NULL && test != right)
+ {
+ if (y == test->y0)
+ x_test = test->x[0];
+ else if(y == test->y1)
+ x_test = test->x[1];
+ else {
+ art_warn ("internal error in add_point: y=%.16f is between %.16f and %.16f\n", y, test->y0, test->y1);
+ x_test = test->x[1];
+ art_report_error();
+ }
+
+ for (;;)
+ {
+ if (x_test <= x)
+ result = test;
+ test = test->right;
+ if (test == right)
+ break;
+
+ /* FIXME the following code doesn't do anything (?) */
+ new_x = x_test;
+ if (new_x < x_test)
+ {
+ art_warn ("art_svp_intersect_add_point: non-ascending x\n");
+ }
+ x_test = new_x;
+ }
+ }
+ return result;
+}
+
+static void
+art_svp_intersect_swap_active (ArtIntersectCtx *ctx,
+ ArtActiveSeg *left_seg, ArtActiveSeg *right_seg)
+{
+ if((left_seg && left_seg->right != right_seg) ||
+ (right_seg && right_seg->left != left_seg)) {
+ art_warn("error: active list in disarray\n");
+ art_report_error();
+ }
+
+ right_seg->left = left_seg->left;
+ if (right_seg->left != NULL)
+ right_seg->left->right = right_seg;
+ else
+ ctx->active_head = right_seg;
+ left_seg->right = right_seg->right;
+ if (left_seg->right != NULL)
+ left_seg->right->left = left_seg;
+ left_seg->left = right_seg;
+ right_seg->right = left_seg;
+}
+
+volatile char add0 = 0;
+static double double_precision(double x)
+{
+ /* make sure x has exactly 11 bits exponent and 52 bit mantissa-
+ there is probably a more elegant (or faster) way to trick the compiler
+ into doing this, but this works for now. */
+ unsigned char xx[8];
+ *(double*)xx = x;
+ xx[0]+=add0; xx[1]+=add0; xx[2]+=add0; xx[3]+=add0;
+ xx[4]+=add0; xx[5]+=add0; xx[6]+=add0; xx[7]+=add0;
+ return *(double*)xx;
+}
+
+/**
+ * art_svp_intersect_test_cross: Test crossing of a pair of active segments.
+ * @ctx: Intersector context.
+ * @left_seg: Left segment of the pair.
+ * @right_seg: Right segment of the pair.
+ * @break_flags: Flags indicating whether to break neighbors.
+ *
+ * Tests crossing of @left_seg and @right_seg. If there is a crossing,
+ * inserts the intersection point into both segments.
+ *
+ * Return value: True if the intersection took place at the current
+ * scan line, indicating further iteration is needed.
+ **/
+static art_boolean
+art_svp_intersect_test_cross (ArtIntersectCtx *ctx,
+ ArtActiveSeg *left_seg, ArtActiveSeg *right_seg,
+ int break_flags)
+{
+ double left_x0, left_y0, left_x1;
+ double left_y1 = left_seg->y1;
+ double right_y1 = right_seg->y1;
+ double d;
+
+ const ArtSVPSeg *in_seg;
+ int in_curs;
+ double d0, d1, t;
+ double x, y; /* intersection point */
+
+#ifdef VERBOSE
+ static int count = 0;
+
+ art_dprint ("art_svp_intersect_test_cross %08x <-> %08x: count=%d\n",
+ (unsigned long)left_seg, (unsigned long)right_seg, count++);
+ art_dprint ("%08x = %.16f,%.16f -> %.16f %.16f\n", left_seg,
+ left_seg->x[0], left_seg->y0,
+ left_seg->x[1], left_seg->y1);
+ art_dprint ("(full: %.16f,%.16f -> %.16f %.16f)\n",
+ left_seg->in_seg->points[left_seg->in_curs - 1].x, left_seg->in_seg->points[left_seg->in_curs - 1].y,
+ left_seg->in_seg->points[left_seg->in_curs].x, left_seg->in_seg->points[left_seg->in_curs].y
+ );
+
+ art_dprint ("%08x = %.16f,%.16f -> %.16f %.16f\n", right_seg,
+ right_seg->x[0], right_seg->y0,
+ right_seg->x[1], right_seg->y1);
+ art_dprint ("(full: %.16f,%.16f -> %.16f %.16f)\n",
+ right_seg->in_seg->points[right_seg->in_curs - 1].x, right_seg->in_seg->points[right_seg->in_curs - 1].y,
+ right_seg->in_seg->points[right_seg->in_curs].x, right_seg->in_seg->points[right_seg->in_curs].y
+ );
+#endif
+
+#ifdef CHEAP_SANITYCHECK
+ if (right_seg->x[0] < left_seg->x[(left_seg->flags & ART_ACTIVE_FLAGS_BNEG) ^ 1]) {
+ /* notice: if we test *only* the line equation here, dd might be < 0, even though
+ right_seg was inserted to the right of left_seg correctly, due to numerical
+ instabilities */
+ double dd = right_seg->x[0] * left_seg->a + right_seg->y0 * left_seg->b + left_seg->c;
+ if(dd < 0) {
+ //art_warn ("segment %08x[%d] isn't to the left of %08x[%d]. d=%.16f\n",
+ // left_seg, left_seg->n_stack,
+ // right_seg, right_seg->n_stack,
+ // dd);
+ }
+ }
+#endif
+
+ if (left_seg->y0 == right_seg->y0 && left_seg->x[0] == right_seg->x[0])
+ {
+ /* Top points of left and right segments coincide. This case
+ feels like a bit of duplication - we may want to merge it
+ with the cases below. However, this way, we're sure that this
+ logic makes only localized changes. */
+
+ if (left_y1 < right_y1)
+ {
+ /* Test left (x1, y1) against right segment */
+ double left_x1 = left_seg->x[1];
+
+ if (left_x1 <
+ right_seg->x[(right_seg->flags & ART_ACTIVE_FLAGS_BNEG) ^ 1] ||
+ left_y1 == right_seg->y0)
+ return ART_FALSE;
+ d = left_x1 * right_seg->a + left_y1 * right_seg->b + right_seg->c;
+ if (d < -EPSILON_A)
+
+ return ART_FALSE;
+ else if (d < EPSILON_A) /* should we use zero here? */
+ {
+#ifdef VERBOSE
+ art_dprint("break %08x because of common top point, left_y1 < right_y1\n", right_seg);
+#endif
+ /* I'm unsure about the break flags here. */
+ double right_x1 = art_svp_intersect_break (ctx, right_seg,
+ left_x1, left_y1,
+ ART_BREAK_RIGHT);
+
+ /* this is always true due to ART_BREAK_RIGHT right_x1>=left_x1 if
+ _break uses x_ref clipping */
+ if (left_x1 <= right_x1) {
+ return ART_FALSE;
+ }
+ }
+ }
+ else if (left_y1 > right_y1)
+ {
+ /* Test right (x1, y1) against left segment */
+ double right_x1 = right_seg->x[1];
+
+ if (right_x1 > left_seg->x[left_seg->flags & ART_ACTIVE_FLAGS_BNEG] ||
+ right_y1 == left_seg->y0)
+
+ return ART_FALSE;
+ d = right_x1 * left_seg->a + right_y1 * left_seg->b + left_seg->c;
+ if (d > EPSILON_A)
+ return ART_FALSE;
+ else if (d > -EPSILON_A) /* should we use zero here? */
+ {
+#ifdef VERBOSE
+ art_dprint("break %08x because of common top point, left_y1 > right_y1\n", left_seg);
+#endif
+ /* See above regarding break flags. */
+ double left_x1 = art_svp_intersect_break (ctx, left_seg,
+ right_x1, right_y1,
+ ART_BREAK_LEFT);
+
+ /* this is always true, due to ART_BREAK_LEFT left_x1<=right_x1, if
+ _break uses x_ref clipping
+ */
+ if (left_x1 <= right_x1) {
+ return ART_FALSE;
+ }
+ }
+ }
+ else /* left_y1 == right_y1 */
+ {
+ double left_x1 = left_seg->x[1];
+ double right_x1 = right_seg->x[1];
+
+
+ if (left_x1 <= right_x1)
+ return ART_FALSE;
+ }
+
+ //int wind_left = left_seg->wind_left;
+ //int wind_right = right_seg->wind_left;
+ art_svp_intersect_swap_active (ctx, left_seg, right_seg);
+ //left_seg->wind_left = wind_right;
+ //right_seg->wind_left = wind_left;
+
+ return ART_TRUE;
+ }
+
+ if (left_y1 < right_y1)
+ {
+ /* Test left (x1, y1) against right segment */
+ double left_x1 = left_seg->x[1];
+
+ if (left_x1 <
+ right_seg->x[(right_seg->flags & ART_ACTIVE_FLAGS_BNEG) ^ 1] ||
+ left_y1 == right_seg->y0)
+ return ART_FALSE;
+
+ if(left_y1 < right_seg->y0) {
+ art_warn("left_y1 < right_seg->y0\n");
+ return ART_FALSE;
+ }
+
+ /* we might want to output a warning for left_y1 < right_seg->y0 */
+
+ d = left_x1 * right_seg->a + left_y1 * right_seg->b + right_seg->c;
+ if (d < -EPSILON_A)
+ return ART_FALSE;
+ else if (d < EPSILON_A)
+ {
+#ifdef VERBOSE
+ art_dprint("break %08x at %.16f because left_y1 < right_y1\n", right_seg, left_y1);
+ art_dprint ("%08x = %.16f,%.16f -> %.16f %.16f\n", right_seg,
+ right_seg->x[0], right_seg->y0,
+ right_seg->x[1], right_seg->y1);
+#endif
+ double right_x1 = art_svp_intersect_break (ctx, right_seg,
+ left_x1, left_y1,
+ ART_BREAK_RIGHT);
+#ifdef VERBOSE
+ art_dprint("after break:\n", right_seg);
+ art_dprint ("%08x = %.16f,%.16f -> %.16f %.16f\n", right_seg,
+ right_seg->x[0], right_seg->y0,
+ right_seg->x[1], right_seg->y1);
+#endif
+ /* this is always true if _break uses x_ref clipping */
+ if (left_x1 <= right_x1)
+ return ART_FALSE;
+ }
+ }
+ else if (left_y1 > right_y1)
+ {
+ /* Test right (x1, y1) against left segment */
+ double right_x1 = right_seg->x[1];
+
+ if (right_x1 > left_seg->x[left_seg->flags & ART_ACTIVE_FLAGS_BNEG] ||
+ right_y1 == left_seg->y0)
+ return ART_FALSE;
+
+ if(right_y1 < left_seg->y0) {
+ art_warn("left_y1 < right_seg->y0\n");
+ return ART_FALSE;
+ }
+
+ /* we might want to output a warning for right_y1 < left_seg->y0 */
+
+ d = right_x1 * left_seg->a + right_y1 * left_seg->b + left_seg->c;
+ if (d > EPSILON_A)
+ return ART_FALSE;
+ else if (d > -EPSILON_A)
+ {
+#ifdef VERBOSE
+ art_dprint("break %08x because left_y1 > right_y1\n", right_seg);
+#endif
+ double left_x1 = art_svp_intersect_break (ctx, left_seg,
+ right_x1, right_y1,
+ ART_BREAK_LEFT);
+ /* this is always true if _break uses x_ref clipping */
+ if (left_x1 <= right_x1)
+ return ART_FALSE;
+ }
+ }
+ else /* left_y1 == right_y1 */
+ {
+ double left_x1 = left_seg->x[1];
+ double right_x1 = right_seg->x[1];
+
+ if (left_x1 <= right_x1)
+ return ART_FALSE;
+ }
+
+
+ /* The segments cross. Find the intersection point. */
+
+ in_seg = left_seg->in_seg;
+ in_curs = left_seg->in_curs;
+ left_x0 = in_seg->points[in_curs - 1].x;
+ left_y0 = in_seg->points[in_curs - 1].y;
+ left_x1 = in_seg->points[in_curs].x;
+ left_y1 = in_seg->points[in_curs].y;
+
+#if 0
+ /* check for endpoint = firstpoint cases */
+ if(left_seg->y0 == right_seg->y1 && left_seg->x[0] == right_seg->x[1])
+ return ART_FALSE;
+ if(left_seg->y1 == right_seg->y0 && left_seg->x[1] == right_seg->x[0])
+ return ART_FALSE;
+#endif
+
+ d0 = left_x0 * right_seg->a + left_y0 * right_seg->b + right_seg->c;
+ d1 = left_x1 * right_seg->a + left_y1 * right_seg->b + right_seg->c;
+ if (d0 == d1)
+ {
+ x = left_x0;
+ y = left_y0;
+ }
+ else
+ {
+ /* Is this division always safe? It could possibly overflow. */
+ t = d0 / (d0 - d1);
+ if (t <= 0)
+ {
+ x = left_x0;
+ y = left_y0;
+ }
+ else if (t >= 1)
+ {
+ x = left_x1;
+ y = left_y1;
+ }
+ else
+ {
+ x = left_x0 + t * (left_x1 - left_x0);
+ y = left_y0 + t * (left_y1 - left_y0);
+ }
+ }
+
+ /* Make sure intersection point is within bounds of right seg. */
+ if (y < right_seg->y0)
+ {
+ x = right_seg->x[0];
+ y = right_seg->y0;
+ }
+ else if (y > right_seg->y1)
+ {
+ x = right_seg->x[1];
+ y = right_seg->y1;
+ }
+ else if (x < right_seg->x[(right_seg->flags & ART_ACTIVE_FLAGS_BNEG) ^ 1])
+ x = right_seg->x[(right_seg->flags & ART_ACTIVE_FLAGS_BNEG) ^ 1];
+ else if (x > right_seg->x[right_seg->flags & ART_ACTIVE_FLAGS_BNEG])
+ x = right_seg->x[right_seg->flags & ART_ACTIVE_FLAGS_BNEG];
+
+ x = double_precision(x);
+ y = double_precision(y);
+
+ assert(ctx->y >= left_seg->y0);
+#ifdef VERBOSE
+ art_dprint ("intersect at %.16f %.16f\n", x, y);
+#endif
+
+
+ if(y < ctx->y) {
+ /* as we use the full segment length (not just the subsegment currently
+ under evaluation), intersection points may be above the current scanline.
+ As we're not able to process these anymore, we also don't need to add
+ anything to the active list or pq.
+
+ Intersection points above the current scanline happen if an
+ intersection is handled twice- once when the line is inserted, and
+ once when e.g. some other intersection point triggers insert_cross.
+ */
+ art_warn ("previously unhandled intersection point %.16f %.16f (dy=%.16f)\n", x, y, ctx->y - y);
+ return ART_FALSE;
+ }
+
+ if(y > left_seg->y1) {
+ /* not within the subsegment we're currently looking into- this is not an intersection */
+ return ART_FALSE;
+ }
+
+ if (y == left_seg->y0)
+ {
+ if (y != right_seg->y0)
+ {
+#ifdef VERBOSE
+ art_dprint ("art_svp_intersect_test_cross: intersection (%.16f, %.16f) matches former y0 of %08x, [%08x]\n",
+ x, y, (unsigned long)left_seg, (unsigned long)right_seg);
+#endif
+ art_svp_intersect_push_pt (ctx, right_seg, x, y);
+ if ((break_flags & ART_BREAK_RIGHT) && right_seg->right != NULL)
+ art_svp_intersect_add_point (ctx, x, y, right_seg->right,
+ break_flags);
+ }
+ else
+ {
+#ifdef VERBOSE
+ art_dprint ("art_svp_intersect_test_cross: intersection (%.16f, %.16f) at current scan line (y=ly0=ry0)\n",
+ x, y, (unsigned long)left_seg, (unsigned long)right_seg);
+#endif
+ /* Intersection takes place at current scan line, with
+ left->x0 <= x <= right->x0, left->x0 != right->x0.
+
+ This happens if one of the lines is horizontal, or very near
+ horizontal. (true horizontal lines are processed by _horiz())
+
+ Process immediately rather than queueing intersection point into
+ priq. */
+ ArtActiveSeg *winner, *loser;
+
+ /* Choose "most vertical" segement */
+ if (left_seg->a > right_seg->a)
+ {
+ winner = left_seg;
+ loser = right_seg;
+ }
+ else
+ {
+ winner = right_seg;
+ loser = left_seg;
+ }
+#ifdef VERBOSE
+ art_dprint (" x = %.16f\n", x);
+ art_dprint (" loser->x[0] = %.16f\n", loser->x[0]);
+ art_dprint ("winner->x[0] = %.16f\n", winner->x[0]);
+#endif
+ loser->x[0] = winner->x[0];
+ loser->horiz_x = loser->x[0];
+ loser->horiz_delta_wind += loser->delta_wind;
+ winner->horiz_delta_wind -= loser->delta_wind;
+
+ art_svp_intersect_swap_active (ctx, left_seg, right_seg);
+ return ART_TRUE;
+ }
+ }
+ else if (y == right_seg->y0)
+ {
+#ifdef VERBOSE
+ art_dprint ("*** art_svp_intersect_test_cross: intersection (%.16f, %.16f) matches latter y0 of [%08x], %08x\n",
+ x, y, (unsigned long)left_seg, (unsigned long)right_seg);
+ art_dprint ("%08x = %.16f,%.16f -> %.16f %.16f\n", left_seg,
+ left_seg->x[0], left_seg->y0,
+ left_seg->x[1], left_seg->y1);
+ art_dprint ("%08x = %.16f,%.16f -> %.16f %.16f\n", right_seg,
+ right_seg->x[0], right_seg->y0,
+ right_seg->x[1], right_seg->y1);
+
+#endif
+ art_svp_intersect_push_pt (ctx, left_seg, x, y);
+ if ((break_flags & ART_BREAK_LEFT) && left_seg->left != NULL)
+ art_svp_intersect_add_point (ctx, x, y, left_seg->left,
+ break_flags);
+ }
+ else
+ {
+#ifdef VERBOSE
+ art_dprint ("Inserting (%.16f, %.16f) into %08x, %08x\n",
+ x, y, (unsigned long)left_seg, (unsigned long)right_seg);
+#endif
+ /* Insert the intersection point into both segments. */
+ art_svp_intersect_push_pt (ctx, left_seg, x, y);
+ art_svp_intersect_push_pt (ctx, right_seg, x, y);
+ if ((break_flags & ART_BREAK_LEFT) && left_seg->left != NULL)
+ art_svp_intersect_add_point (ctx, x, y, left_seg->left, ART_BREAK_LEFT | ART_BREAK_RIGHT);
+ if ((break_flags & ART_BREAK_RIGHT) && right_seg->right != NULL)
+ art_svp_intersect_add_point (ctx, x, y, right_seg->right, ART_BREAK_LEFT | ART_BREAK_RIGHT);
+ }
+ return ART_FALSE;
+}
+
+/**
+ * art_svp_intersect_active_delete: Delete segment from active list.
+ * @ctx: Intersection context.
+ * @seg: Segment to delete.
+ *
+ * Deletes @seg from the active list.
+ **/
+static /* todo inline */ void
+art_svp_intersect_active_delete (ArtIntersectCtx *ctx, ArtActiveSeg *seg)
+{
+ ArtActiveSeg *left = seg->left, *right = seg->right;
+
+ if (left != NULL)
+ left->right = right;
+ else
+ ctx->active_head = right;
+ if (right != NULL)
+ right->left = left;
+}
+
+/**
+ * art_svp_intersect_active_free: Free an active segment.
+ * @seg: Segment to delete.
+ *
+ * Frees @seg.
+ **/
+static /* todo inline */ void
+art_svp_intersect_active_free (ArtActiveSeg *seg)
+{
+ art_free (seg->stack);
+#ifdef VERBOSE
+ art_dprint ("Freeing %08x\n", (unsigned long) seg);
+#else
+ // !!!
+ art_free (seg);
+#endif
+}
+
+/**
+ * art_svp_intersect_insert_cross: Test crossings of newly inserted line.
+ *
+ * Tests @seg against its left and right neighbors for intersections.
+ * Precondition: the line in @seg is not purely horizontal.
+ **/
+static void
+art_svp_intersect_insert_cross (ArtIntersectCtx *ctx,
+ ArtActiveSeg *seg)
+{
+ ArtActiveSeg *left = seg, *right = seg;
+
+ for (;;)
+ {
+ if (left != NULL)
+ {
+ ArtActiveSeg *leftc;
+
+ for (leftc = left->left; leftc != NULL; leftc = leftc->left)
+ if (!(leftc->flags & ART_ACTIVE_FLAGS_DEL))
+ break;
+ if (leftc != NULL &&
+ art_svp_intersect_test_cross (ctx, leftc, left,
+ ART_BREAK_LEFT))
+ {
+ if (left == right || right == NULL)
+ right = left->right;
+ }
+ else
+ {
+ left = NULL;
+ }
+ }
+ else if (right != NULL && right->right != NULL)
+ {
+ ArtActiveSeg *rightc;
+
+ for (rightc = right->right; rightc != NULL; rightc = rightc->right)
+ if (!(rightc->flags & ART_ACTIVE_FLAGS_DEL))
+ break;
+ if (rightc != NULL &&
+ art_svp_intersect_test_cross (ctx, right, rightc,
+ ART_BREAK_RIGHT))
+ {
+ if (left == right || left == NULL)
+ left = right->left;
+ }
+ else
+ {
+ right = NULL;
+ }
+ }
+ else
+ break;
+ }
+}
+
+/**
+ * art_svp_intersect_horiz: Add horizontal line segment.
+ * @ctx: Intersector context.
+ * @seg: Segment on which to add horizontal line.
+ * @x0: Old x position.
+ * @x1: New x position.
+ *
+ * Adds a horizontal line from @x0 to @x1, and updates the current
+ * location of @seg to @x1.
+ **/
+static void
+art_svp_intersect_horiz (ArtIntersectCtx *ctx, ArtActiveSeg *seg,
+ double x0, double x1)
+{
+ ArtActiveSeg *hs;
+
+ if (x0 == x1)
+ return;
+
+#ifdef VERBOSE
+ art_dprint("horiz: seg=%08x x0=%f x1=%f segid=%08x flags=%s delta_wind=%d\n", seg, x0, x1, seg->seg_id,
+ seg->flags & ART_ACTIVE_FLAGS_OUT?"out":"", seg->delta_wind);
+#endif
+
+ hs = art_new (ArtActiveSeg, 1);
+
+ hs->flags = ART_ACTIVE_FLAGS_DEL | (seg->flags & ART_ACTIVE_FLAGS_OUT);
+ if (seg->flags & ART_ACTIVE_FLAGS_OUT)
+ {
+ ArtSvpWriter *swr = ctx->out;
+
+ swr->add_point (swr, seg->seg_id, x0, ctx->y);
+ }
+ hs->seg_id = seg->seg_id;
+ hs->horiz_x = x0;
+ hs->horiz_delta_wind = seg->delta_wind;
+ hs->stack = NULL;
+
+ /* Ideally, the (a, b, c) values will never be read. However, there
+ are probably some tests remaining that don't check for _DEL
+ before evaluating the line equation. For those, these
+ initializations will at least prevent a UMR of the values, which
+ can crash on some platforms. */
+ hs->a = 0.0;
+ hs->b = 0.0;
+ hs->c = 0.0;
+
+ seg->horiz_delta_wind -= seg->delta_wind;
+
+ art_svp_intersect_add_horiz (ctx, hs);
+
+ if (x0 > x1)
+ {
+ ArtActiveSeg *left;
+ art_boolean first = ART_TRUE;
+
+ for (left = seg->left; left != NULL; left = seg->left)
+ {
+ int left_bneg = left->flags & ART_ACTIVE_FLAGS_BNEG;
+
+ if (left->x[left_bneg] <= x1)
+ break;
+ if (left->x[left_bneg ^ 1] <= x1 &&
+ x1 * left->a + ctx->y * left->b + left->c >= 0)
+ break;
+ if (left->y0 != ctx->y && left->y1 != ctx->y)
+ {
+ art_svp_intersect_break (ctx, left, x1, ctx->y, ART_BREAK_LEFT);
+ }
+#ifdef VERBOSE
+ art_dprint ("x0=%.16f > x1=%.16f, swapping %08x, %08x\n",
+ x0, x1, (unsigned long)left, (unsigned long)seg);
+#endif
+ art_svp_intersect_swap_active (ctx, left, seg);
+ if (first && left->right != NULL)
+ {
+ art_svp_intersect_test_cross (ctx, left, left->right,
+ ART_BREAK_RIGHT);
+ first = ART_FALSE;
+ }
+ }
+ }
+ else
+ {
+ ArtActiveSeg *right;
+ art_boolean first = ART_TRUE;
+
+ for (right = seg->right; right != NULL; right = seg->right)
+ {
+ int right_bneg = right->flags & ART_ACTIVE_FLAGS_BNEG;
+
+ if (right->x[right_bneg ^ 1] >= x1)
+ break;
+ if (right->x[right_bneg] >= x1 &&
+ x1 * right->a + ctx->y * right->b + right->c <= 0)
+ break;
+ if (right->y0 != ctx->y && right->y1 != ctx->y)
+ {
+ art_svp_intersect_break (ctx, right, x1, ctx->y,
+ ART_BREAK_LEFT);
+ }
+#ifdef VERBOSE
+ art_dprint ("[right]x0=%.16f < x1=%.16f, swapping %08x, %08x\n",
+ x0, x1, (unsigned long)seg, (unsigned long)right);
+#endif
+ art_svp_intersect_swap_active (ctx, seg, right);
+ if (first && right->left != NULL)
+ {
+ art_svp_intersect_test_cross (ctx, right->left, right,
+ ART_BREAK_RIGHT);
+ first = ART_FALSE;
+ }
+ }
+ }
+
+ seg->x[0] = x1;
+ seg->x[1] = x1;
+ seg->horiz_x = x1;
+ seg->flags &= ~ART_ACTIVE_FLAGS_OUT;
+}
+
+/**
+ * art_svp_intersect_insert_line: Insert a line into the active list.
+ * @ctx: Intersector context.
+ * @seg: Segment containing line to insert.
+ *
+ * Inserts the line into the intersector context, taking care of any
+ * intersections, and adding the appropriate horizontal points to the
+ * active list.
+ **/
+static void
+art_svp_intersect_insert_line (ArtIntersectCtx *ctx, ArtActiveSeg *seg)
+{
+ if (seg->y1 == seg->y0)
+ {
+#ifdef VERBOSE
+ art_dprint ("art_svp_intersect_insert_line(%d): %08x is horizontal\n", seg->flags&ART_ACTIVE_FLAGS_IN_ACTIVE, (unsigned long)seg);
+#endif
+ art_svp_intersect_horiz (ctx, seg, seg->x[0], seg->x[1]);
+ }
+ else
+ {
+#ifdef VERBOSE
+ art_dprint ("art_svp_intersect_insert_line(%d): %08x is non-horizontal\n", seg->flags&ART_ACTIVE_FLAGS_IN_ACTIVE, (unsigned long)seg);
+#endif
+ art_svp_intersect_insert_cross (ctx, seg);
+ art_svp_intersect_add_horiz (ctx, seg);
+ }
+
+ seg->flags |= ART_ACTIVE_FLAGS_IN_ACTIVE; //q
+}
+
+static void
+art_svp_intersect_process_intersection (ArtIntersectCtx *ctx,
+ ArtActiveSeg *seg)
+{
+ int n_stack = --seg->n_stack;
+ seg->x[1] = seg->stack[n_stack - 1].x;
+ seg->y1 = seg->stack[n_stack - 1].y;
+ seg->x[0] = seg->stack[n_stack].x;
+ seg->y0 = seg->stack[n_stack].y;
+ seg->horiz_x = seg->x[0];
+#ifdef VERBOSE
+ art_dprint("process intersection %08x (%.16f,%.16f-%.16f,%.16f)\n", seg, seg->x[0], seg->y0, seg->x[1], seg->y1);
+#endif
+ art_svp_intersect_insert_line (ctx, seg);
+}
+
+static void
+art_svp_intersect_advance_cursor (ArtIntersectCtx *ctx, ArtActiveSeg *seg,
+ ArtPriPoint *pri_pt)
+{
+ const ArtSVPSeg *in_seg = seg->in_seg;
+ int in_curs = seg->in_curs;
+ ArtSvpWriter *swr = seg->flags & ART_ACTIVE_FLAGS_OUT ? ctx->out : NULL;
+
+ if (swr != NULL)
+ swr->add_point (swr, seg->seg_id, seg->x[1], seg->y1);
+ if (in_curs + 1 >= in_seg->n_points)
+ {
+ ArtActiveSeg *left = seg->left, *right = seg->right;
+
+#if 0
+ if (swr != NULL)
+ swr->close_segment (swr, seg->seg_id);
+ seg->flags &= ~ART_ACTIVE_FLAGS_OUT;
+#endif
+ seg->flags |= ART_ACTIVE_FLAGS_DEL;
+ art_svp_intersect_add_horiz (ctx, seg);
+ art_svp_intersect_active_delete (ctx, seg);
+ if (left != NULL && right != NULL)
+ art_svp_intersect_test_cross (ctx, left, right,
+ ART_BREAK_LEFT | ART_BREAK_RIGHT);
+ art_free (pri_pt);
+ }
+ else
+ {
+ seg->horiz_x = seg->x[1];
+
+ art_svp_intersect_setup_seg (seg, pri_pt);
+ art_pri_insert (ctx->pq, pri_pt);
+ art_svp_intersect_insert_line (ctx, seg);
+ }
+}
+
+static void
+art_svp_intersect_add_seg (ArtIntersectCtx *ctx, const ArtSVPSeg *in_seg)
+{
+ ArtActiveSeg *seg = art_new (ArtActiveSeg, 1);
+ ArtActiveSeg *test;
+ double x0, y0;
+ ArtActiveSeg *beg_range;
+ ArtActiveSeg *last = NULL;
+ ArtActiveSeg *left, *right;
+ ArtPriPoint *pri_pt = art_new (ArtPriPoint, 1);
+
+ seg->flags = 0;
+ seg->in_seg = in_seg;
+ seg->in_curs = 0;
+
+ seg->n_stack_max = 4;
+ seg->stack = art_new (ArtPoint, seg->n_stack_max);
+
+ seg->horiz_delta_wind = 0;
+
+ seg->wind_left = 0;
+
+ pri_pt->user_data = seg;
+ art_svp_intersect_setup_seg (seg, pri_pt);
+ art_pri_insert (ctx->pq, pri_pt);
+
+ /* Find insertion place for new segment */
+ /* This is currently a left-to-right scan, but should be replaced
+ with a binary search as soon as it's validated. */
+
+ x0 = in_seg->points[0].x;
+ y0 = in_seg->points[0].y;
+ beg_range = NULL;
+ for (test = ctx->active_head; test != NULL; test = test->right)
+ {
+ double d;
+ int test_bneg = test->flags & ART_ACTIVE_FLAGS_BNEG;
+
+ if (x0 < test->x[test_bneg])
+ {
+ if (x0 < test->x[test_bneg ^ 1]) {
+#ifdef VERBOSE
+ art_dprint("inserting segment %08x before %08x (x0 < xmin)\n", seg, test);
+#endif
+ break;
+ }
+ d = x0 * test->a + y0 * test->b + test->c;
+ if (d < 0) {
+#ifdef VERBOSE
+ art_dprint("inserting segment %08x before %08x (d = %.16f)\n", seg, test, d);
+#endif
+ break;
+ }
+#ifdef VERBOSE
+ art_dprint("segment %08x is to the right of %08x d=%.16f\n", seg, test, d);
+#endif
+ } else {
+#ifdef VERBOSE
+ d = x0 * test->a + y0 * test->b + test->c;
+ art_dprint("segment %08x is to the right of %08x d=%.16f (not used)\n", seg, test, d);
+#endif
+ }
+ last = test;
+ }
+
+ left = art_svp_intersect_add_point (ctx, x0, y0, last, ART_BREAK_LEFT | ART_BREAK_RIGHT);
+
+#ifdef VERBOSE
+ art_dprint("left=%08x x0=%.16f y=%.16f\n", left, x0, y0);
+#endif
+
+ seg->left = left;
+ if (left == NULL)
+ {
+ right = ctx->active_head;
+ ctx->active_head = seg;
+ }
+ else
+ {
+ right = left->right;
+ left->right = seg;
+ }
+ seg->right = right;
+ if (right != NULL)
+ right->left = seg;
+
+ seg->delta_wind = in_seg->dir ? 1 : -1;
+ seg->horiz_x = x0;
+
+ art_svp_intersect_insert_line (ctx, seg);
+}
+
+#ifdef SANITYCHECK
+static void
+art_svp_intersect_sanitycheck_winding (ArtIntersectCtx *ctx)
+{
+#if 0
+ /* At this point, we seem to be getting false positives, so it's
+ turned off for now. */
+
+ ArtActiveSeg *seg;
+ int winding_number = 0;
+
+ for (seg = ctx->active_head; seg != NULL; seg = seg->right)
+ {
+ /* Check winding number consistency. */
+ if (seg->flags & ART_ACTIVE_FLAGS_OUT)
+ {
+ if (winding_number != seg->wind_left)
+ art_warn ("*** art_svp_intersect_sanitycheck_winding: seg %08x has wind_left of %d, expected %d\n",
+ (unsigned long) seg, seg->wind_left, winding_number);
+ winding_number = seg->wind_left + seg->delta_wind;
+ }
+ }
+ if (winding_number != 0)
+ art_warn ("*** art_svp_intersect_sanitycheck_winding: non-balanced winding number %d\n",
+ winding_number);
+#endif
+}
+#endif
+
+/**
+ * art_svp_intersect_horiz_commit: Commit points in horiz list to output.
+ * @ctx: Intersection context.
+ *
+ * The main function of the horizontal commit is to output new
+ * points to the output writer.
+ *
+ * This "commit" pass is also where winding numbers are assigned,
+ * because doing it here provides much greater tolerance for inputs
+ * which are not in strict SVP order.
+ *
+ * Each cluster in the horiz_list contains both segments that are in
+ * the active list (ART_ACTIVE_FLAGS_DEL is false) and that are not,
+ * and are scheduled to be deleted (ART_ACTIVE_FLAGS_DEL is true). We
+ * need to deal with both.
+ **/
+static void
+art_svp_intersect_horiz_commit (ArtIntersectCtx *ctx)
+{
+ ArtActiveSeg *seg;
+ int winding_number = 0; /* initialization just to avoid warning */
+ int horiz_wind = 0;
+ double last_x = 0; /* initialization just to avoid warning */
+
+#ifdef VERBOSE
+ art_dprint ("art_svp_intersect_horiz_commit: y=%.16f\n", ctx->y);
+ for (seg = ctx->horiz_first; seg != NULL; seg = seg->horiz_right)
+ art_dprint (" %08x: %.16f %+d segid=%d\n",
+ (unsigned long)seg, seg->horiz_x, seg->horiz_delta_wind, seg->seg_id);
+#endif
+
+ /* Output points to svp writer. */
+ for (seg = ctx->horiz_first; seg != NULL;)
+ {
+ /* Find a cluster with common horiz_x, */
+ ArtActiveSeg *curs;
+ double x = seg->horiz_x;
+
+ /* Generate any horizontal segments. */
+ if (horiz_wind != 0)
+ {
+ ArtSvpWriter *swr = ctx->out;
+ int seg_id;
+
+#ifdef VERBOSE
+ art_dprint ("generate horizontal segment: y=%.16f x=%.16f-%.16f wind=%d horiz_wind=%d\n", ctx->y, last_x, x, winding_number, horiz_wind);
+#endif
+ seg_id = swr->add_segment (swr, winding_number, horiz_wind,
+ last_x, ctx->y);
+ swr->add_point (swr, seg_id, x, ctx->y);
+ swr->close_segment (swr, seg_id);
+ }
+
+ /* Find first active segment in cluster. */
+
+ for (curs = seg; curs != NULL && curs->horiz_x == x;
+ curs = curs->horiz_right)
+ if (!(curs->flags & ART_ACTIVE_FLAGS_DEL))
+ break;
+
+ if (curs != NULL && curs->horiz_x == x)
+ {
+ /* There exists at least one active segment in this cluster. */
+
+ /* Find beginning of cluster. */
+ for (; curs->left != NULL; curs = curs->left)
+ if (curs->left->horiz_x != x)
+ break;
+
+ if (curs->left != NULL)
+ winding_number = curs->left->wind_left + curs->left->delta_wind;
+ else
+ winding_number = 0;
+
+ do
+ {
+#ifdef VERBOSE
+ art_dprint (" curs %08x: winding_number = %d += %d\n", (unsigned long)curs, winding_number, curs->delta_wind);
+#endif
+ if (!(curs->flags & ART_ACTIVE_FLAGS_OUT) ||
+ curs->wind_left != winding_number)
+ {
+ ArtSvpWriter *swr = ctx->out;
+
+ if (curs->flags & ART_ACTIVE_FLAGS_OUT)
+ {
+ swr->add_point (swr, curs->seg_id,
+ curs->horiz_x, ctx->y);
+ swr->close_segment (swr, curs->seg_id);
+ }
+
+ curs->seg_id = swr->add_segment (swr, winding_number,
+ curs->delta_wind,
+ x, ctx->y);
+ curs->flags |= ART_ACTIVE_FLAGS_OUT;
+ }
+ curs->wind_left = winding_number;
+ winding_number += curs->delta_wind;
+ curs = curs->right;
+ }
+ while (curs != NULL && curs->horiz_x == x);
+ }
+
+ /* Skip past cluster. */
+ do
+ {
+ ArtActiveSeg *next = seg->horiz_right;
+
+ seg->flags &= ~ART_ACTIVE_FLAGS_IN_HORIZ;
+ horiz_wind += seg->horiz_delta_wind;
+ seg->horiz_delta_wind = 0;
+ if (seg->flags & ART_ACTIVE_FLAGS_DEL)
+ {
+ if (seg->flags & ART_ACTIVE_FLAGS_OUT)
+ {
+ ArtSvpWriter *swr = ctx->out;
+ swr->close_segment (swr, seg->seg_id);
+ }
+ art_svp_intersect_active_free (seg);
+ }
+ seg = next;
+ }
+ while (seg != NULL && seg->horiz_x == x);
+
+ last_x = x;
+ }
+ ctx->horiz_first = NULL;
+ ctx->horiz_last = NULL;
+#ifdef SANITYCHECK
+ art_svp_intersect_sanitycheck_winding (ctx);
+#endif
+}
+
+#ifdef SANITYCHECK
+static void
+art_svp_intersect_sanitycheck (ArtIntersectCtx *ctx, double y)
+{
+ ArtActiveSeg *seg;
+ ArtActiveSeg *last = NULL;
+ double d;
+
+#ifdef VERbOSE
+ art_dprint ("Active list (y = %.16f (new: %.16f)):\n", ctx->y, y);
+#endif
+
+ for (seg = ctx->active_head; seg != NULL; seg = seg->right)
+ {
+#ifdef VERBOSE
+ char c1=' ',c2=' ',e1=' ';
+ if(seg->y0 > ctx->y) c1='!';
+ if(seg->y0 > y) c2='!';
+ if(seg->y0 > seg->y1) e1='E';
+#endif
+
+ if (seg->left != last)
+ {
+ art_warn ("*** art_svp_intersect_sanitycheck: last=%08x, seg->left=%08x\n",
+ (unsigned long)last, (unsigned long)seg->left);
+ }
+ if (last != NULL)
+ {
+ /* pairwise compare with previous seg */
+
+ /* First the top. */
+ if (last->y0 < seg->y0)
+ {
+ }
+ else
+ {
+ }
+
+ /* Then the bottom. */
+ if (last->y1 < seg->y1)
+ {
+ if (!((last->x[1] <
+ seg->x[(seg->flags & ART_ACTIVE_FLAGS_BNEG) ^ 1]) ||
+ last->y1 == seg->y0))
+ {
+ d = last->x[1] * seg->a + last->y1 * seg->b + seg->c;
+ if (d >= EPSILON_A) {
+ art_warn ("*** bottom (%.16f, %.16f) of %08x is not clear of %08x to right (d = %g)\n",
+ last->x[1], last->y1, (unsigned long) last,
+ (unsigned long) seg, d);
+ art_report_error();
+ } else {
+#ifdef VERBOSE
+ art_dprint("is to the left (d=%.16f of previous x1,y1) of\n", d);
+#endif
+ }
+ } else {
+#ifdef VERBOSE
+ art_dprint("is to the left (previous x1 < next x%d) of\n", (seg->flags & ART_ACTIVE_FLAGS_BNEG) ^ 1);
+#endif
+ }
+ }
+ else if (last->y1 > seg->y1)
+
+ {
+ if (!((seg->x[1] >
+ last->x[last->flags & ART_ACTIVE_FLAGS_BNEG]) ||
+ seg->y1 == last->y0))
+ {
+ d = seg->x[1] * last->a + seg->y1 * last->b + last->c;
+ if (d < -EPSILON_A) {
+ art_warn ("*** bottom (%.16f, %.16f) of %08x is not clear of %08x to left (d = %.16f)\n",
+ seg->x[1], seg->y1, (unsigned long) seg,
+ (unsigned long) last, d);
+ art_report_error();
+ } else {
+#ifdef VERBOSE
+ art_dprint("is to the left (d=%.16f of next x1,y1) of\n", d);
+#endif
+ }
+ } else {
+#ifdef VERBOSE
+ art_dprint("is to the left (next x1 > previous x%d) of\n", last->flags & ART_ACTIVE_FLAGS_BNEG);
+#endif
+ }
+ }
+ else
+ {
+ if (last->x[1] - seg->x[1] > EPSILON_A) {
+ art_warn ("*** bottoms (%.16f, %.16f) of %08x and (%.16f, %.16f) of %08x out of order\n",
+ last->x[1], last->y1, (unsigned long)last,
+ seg->x[1], seg->y1, (unsigned long)seg);
+ art_report_error();
+ } else {
+#ifdef VERBOSE
+ art_dprint("is to the left (y1s equal, previous x1 < next x1)\n");
+#endif
+ }
+ }
+ }
+
+#ifdef VERBOSE
+ art_dprint ("%c%08x: %c%c %02d (%.16f, %.16f)-(%.16f, %.16f) ",
+ e1,
+ (unsigned long)seg, c1, c2, seg->flags,
+ seg->x[0], seg->y0, seg->x[1], seg->y1);
+#endif
+
+ last = seg;
+ }
+#ifdef VERBOSE
+ art_dprint("\n");
+#endif
+}
+#endif
+
+void
+art_svp_intersector (const ArtSVP *in, ArtSvpWriter *out)
+{
+ ArtIntersectCtx *ctx;
+ ArtPriQ *pq;
+ ArtPriPoint *first_point;
+#ifdef VERBOSE
+ int count = 0;
+#endif
+
+ if (in->n_segs == 0)
+ return;
+
+ current_svp = in;
+
+#ifdef VERBOSE
+ int t;
+ art_dprint("Segments: %d\n", in->n_segs);
+ for(t=0;tn_segs;t++) {
+ const ArtSVPSeg* seg = &in->segs[t];
+ art_dprint("Segment %08x(%d): %d points, %s, BBox: (%f,%f,%f,%f)\n",
+ seg, t, seg->n_points, seg->dir==0?"UP ":"DOWN",
+ seg->bbox.x0, seg->bbox.y0, seg->bbox.x1, seg->bbox.y1);
+ int p;
+ for(p=0;pn_points;p++) {
+ ArtPoint* point = &seg->points[p];
+ art_dprint(" (%.16f,%.16f)\n", point->x, point->y);
+ }
+ }
+ art_dprint("\n");
+#endif
+
+ ctx = art_new (ArtIntersectCtx, 1);
+ ctx->in = in;
+ ctx->out = out;
+ pq = art_pri_new ();
+ ctx->pq = pq;
+
+ ctx->active_head = NULL;
+
+ ctx->horiz_first = NULL;
+ ctx->horiz_last = NULL;
+
+ ctx->in_curs = 0;
+ first_point = art_new (ArtPriPoint, 1);
+ first_point->x = in->segs[0].points[0].x;
+ first_point->y = in->segs[0].points[0].y;
+ first_point->user_data = NULL;
+ ctx->y = first_point->y;
+ art_pri_insert (pq, first_point);
+
+ double lasty = -HUGE_VAL;
+ while (!art_pri_empty (pq))
+ {
+ ArtPriPoint *pri_point = art_pri_choose (pq);
+ ArtActiveSeg *seg = (ArtActiveSeg *)pri_point->user_data;
+
+#ifdef VERBOSE
+ art_dprint ("\nIntersector step %d (%d items in pq)\n", count++, pq->n_items);
+#endif
+#ifdef SANITYCHECK
+ art_svp_intersect_sanitycheck(ctx, pri_point->y);
+#endif
+#ifdef VERBOSE
+ art_dprint ("priq choose (%.16f, %.16f) %08x\n", pri_point->x, pri_point->y,
+ (unsigned long)pri_point->user_data);
+ if(seg) {
+ art_dprint (" %08x = %.16f,%.16f -> %.16f %.16f\n", seg, seg->x[0], seg->y0, seg->x[1], seg->y1);
+ }
+ //int t;
+ //for(t=0;tn_items;t++) {
+ // art_dprint("pq[%d] %.16f,%.16f %08x\n",
+ // t,
+ // pq->items[t]->x,
+ // pq->items[t]->y,
+ // pq->items[t]->user_data);
+ //}
+#endif
+
+ //art_dprint("y=%f %08x\n", pri_point->y, pri_point->user_data);
+ if (ctx->y != pri_point->y)
+ {
+ art_svp_intersect_horiz_commit (ctx);
+ ctx->y = pri_point->y;
+ }
+
+ if(ctx->y < lasty) {
+ art_warn("y decreased\n");
+ art_report_error();
+ }
+
+ if (seg == NULL)
+ {
+ /* Insert new segment from input */
+ const ArtSVPSeg *in_seg = 0;
+
+ while(1) {
+ in_seg = &in->segs[ctx->in_curs++];
+ if(in_seg->n_points > 1)
+ break;
+ if(ctx->in_curs == in->n_segs) {
+ in_seg = 0;
+ break;
+ }
+
+#ifdef VERBOSE
+ art_dprint("ignoring input segment %08x- it only contains %d point(s)\n",
+ in_seg, in_seg->n_points);
+#endif
+ }
+
+ if(in_seg) {
+ int t;
+ int error = 0;
+ for(t=0;tn_points-1;t++) {
+ if(!(in_seg->points[t].y <= in_seg->points[t+1].y)) {
+ error = 1;
+ }
+ }
+ if(error) {
+ art_warn("bad input: contains a segment with descending y\n");
+ for(t=0;tn_points;t++) {
+ art_dprint("%d) %.16f %.16f\n", t, in_seg->points[t].x, in_seg->points[t].y);
+ }
+ art_report_error();
+ }
+
+#ifdef VERBOSE
+ art_dprint("insert new segment from input (%.16f,%.16f) dir=%d\n", in_seg->points[0].x, in_seg->points[0].y, in_seg->dir);
+#endif
+ art_svp_intersect_add_seg (ctx, in_seg);
+ if (ctx->in_curs < in->n_segs)
+ {
+ const ArtSVPSeg *next_seg = &in->segs[ctx->in_curs];
+ pri_point->x = next_seg->points[0].x;
+ pri_point->y = next_seg->points[0].y;
+ /* user_data is already NULL */
+ art_pri_insert (pq, pri_point);
+ }
+ else
+ art_free(pri_point);pri_point =0;
+ } else {
+ art_free(pri_point);pri_point = 0;
+ }
+ }
+ else
+ {
+ int n_stack = seg->n_stack;
+
+ if (n_stack > 1)
+ {
+ art_svp_intersect_process_intersection (ctx, seg);
+ art_free (pri_point);
+ }
+ else
+ {
+ art_svp_intersect_advance_cursor (ctx, seg, pri_point);
+ }
+ }
+ lasty = ctx->y;
+ }
+
+ art_svp_intersect_horiz_commit (ctx);
+
+ art_pri_free (pq);
+ art_free (ctx);
+ current_svp = 0;
+}
diff -Nru swftools-0.9.2+ds1/lib/art/art_svp_intersect.h swftools-0.9.1/lib/art/art_svp_intersect.h
--- swftools-0.9.2+ds1/lib/art/art_svp_intersect.h 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/art/art_svp_intersect.h 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,74 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 2001 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __ART_SVP_INTERSECT_H__
+#define __ART_SVP_INTERSECT_H__
+
+/* The funky new SVP intersector. */
+
+#ifdef LIBART_COMPILATION
+#include "art_svp.h"
+#else
+#include "art_svp.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+extern const ArtSVP* current_svp;
+extern void art_report_error();
+extern int art_error_in_intersector;
+
+#ifndef ART_WIND_RULE_DEFINED
+#define ART_WIND_RULE_DEFINED
+typedef enum {
+ ART_WIND_RULE_NONZERO,
+ ART_WIND_RULE_INTERSECT,
+ ART_WIND_RULE_ODDEVEN,
+ ART_WIND_RULE_POSITIVE
+} ArtWindRule;
+#endif
+
+typedef struct _ArtSvpWriter ArtSvpWriter;
+
+struct _ArtSvpWriter {
+ int (*add_segment) (ArtSvpWriter *self, int wind_left, int delta_wind,
+ double x, double y);
+ void (*add_point) (ArtSvpWriter *self, int seg_id, double x, double y);
+ void (*close_segment) (ArtSvpWriter *self, int seg_id);
+};
+
+ArtSvpWriter *
+art_svp_writer_rewind_new (ArtWindRule rule);
+
+ArtSVP *
+art_svp_writer_rewind_reap (ArtSvpWriter *self);
+
+int
+art_svp_seg_compare (const void *s1, const void *s2);
+
+void
+art_svp_intersector (const ArtSVP *in, ArtSvpWriter *out);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __ART_SVP_INTERSECT_H__ */
diff -Nru swftools-0.9.2+ds1/lib/art/art_svp_ops.c swftools-0.9.1/lib/art/art_svp_ops.c
--- swftools-0.9.2+ds1/lib/art/art_svp_ops.c 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/art/art_svp_ops.c 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,400 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998-2000 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#define noVERBOSE
+
+/* Vector path set operations, over sorted vpaths. */
+
+#include "config.h"
+#include "art_svp_ops.h"
+
+#include "art_misc.h"
+
+#include "art_svp.h"
+#include "art_vpath.h"
+#include "art_svp_vpath.h"
+#include "art_svp.h"
+#ifdef ART_USE_NEW_INTERSECTOR
+#include "art_svp_intersect.h"
+#else
+#include "art_svp_wind.h"
+#endif
+#include "art_vpath_svp.h"
+
+/* Merge the segments of the two svp's. The resulting svp will share
+ segments with args passed in, so be super-careful with the
+ allocation. */
+/**
+ * art_svp_merge: Merge the segments of two svp's.
+ * @svp1: One svp to merge.
+ * @svp2: The other svp to merge.
+ *
+ * Merges the segments of two SVP's into a new one. The resulting
+ * #ArtSVP data structure will share the segments of the argument
+ * svp's, so it is probably a good idea to free it shallowly,
+ * especially if the arguments will be freed with art_svp_free().
+ *
+ * Return value: The merged #ArtSVP.
+ **/
+ArtSVP * art_svp_merge (const ArtSVP *svp1, const ArtSVP *svp2)
+{
+ ArtSVP *svp_new;
+ int ix;
+ int ix1, ix2;
+
+ svp_new = (ArtSVP *)art_alloc (sizeof(ArtSVP) +
+ (svp1->n_segs + svp2->n_segs - 1) *
+ sizeof(ArtSVPSeg));
+ ix1 = 0;
+ ix2 = 0;
+ for (ix = 0; ix < svp1->n_segs + svp2->n_segs; ix++)
+ {
+ if (ix1 < svp1->n_segs &&
+ (ix2 == svp2->n_segs ||
+ art_svp_seg_compare (&svp1->segs[ix1], &svp2->segs[ix2]) < 1))
+ svp_new->segs[ix] = svp1->segs[ix1++];
+ else
+ svp_new->segs[ix] = svp2->segs[ix2++];
+ }
+
+ svp_new->n_segs = ix;
+ return svp_new;
+}
+
+#ifdef VERBOSE
+
+#define XOFF 50
+#define YOFF 700
+
+static void
+print_ps_vpath (ArtVpath *vpath)
+{
+ int i;
+
+ printf ("gsave %d %d translate 1 -1 scale\n", XOFF, YOFF);
+ for (i = 0; vpath[i].code != ART_END; i++)
+ {
+ switch (vpath[i].code)
+ {
+ case ART_MOVETO:
+ printf ("%g %g moveto\n", vpath[i].x, vpath[i].y);
+ break;
+ case ART_LINETO:
+ printf ("%g %g lineto\n", vpath[i].x, vpath[i].y);
+ break;
+ default:
+ break;
+ }
+ }
+ printf ("stroke grestore showpage\n");
+}
+
+#define DELT 4
+
+static void
+print_ps_svp (ArtSVP *vpath)
+{
+ int i, j;
+
+ printf ("%% begin\n");
+ for (i = 0; i < vpath->n_segs; i++)
+ {
+ printf ("%g setgray\n", vpath->segs[i].dir ? 0.7 : 0);
+ for (j = 0; j < vpath->segs[i].n_points; j++)
+ {
+ printf ("%g %g %s\n",
+ XOFF + vpath->segs[i].points[j].x,
+ YOFF - vpath->segs[i].points[j].y,
+ j ? "lineto" : "moveto");
+ }
+ printf ("%g %g moveto %g %g lineto %g %g lineto %g %g lineto stroke\n",
+ XOFF + vpath->segs[i].points[0].x - DELT,
+ YOFF - DELT - vpath->segs[i].points[0].y,
+ XOFF + vpath->segs[i].points[0].x - DELT,
+ YOFF - vpath->segs[i].points[0].y,
+ XOFF + vpath->segs[i].points[0].x + DELT,
+ YOFF - vpath->segs[i].points[0].y,
+ XOFF + vpath->segs[i].points[0].x + DELT,
+ YOFF - DELT - vpath->segs[i].points[0].y);
+ printf ("%g %g moveto %g %g lineto %g %g lineto %g %g lineto stroke\n",
+ XOFF + vpath->segs[i].points[j - 1].x - DELT,
+ YOFF + DELT - vpath->segs[i].points[j - 1].y,
+ XOFF + vpath->segs[i].points[j - 1].x - DELT,
+ YOFF - vpath->segs[i].points[j - 1].y,
+ XOFF + vpath->segs[i].points[j - 1].x + DELT,
+ YOFF - vpath->segs[i].points[j - 1].y,
+ XOFF + vpath->segs[i].points[j - 1].x + DELT,
+ YOFF + DELT - vpath->segs[i].points[j - 1].y);
+ printf ("stroke\n");
+ }
+
+ printf ("showpage\n");
+}
+#endif
+
+#ifndef ART_USE_NEW_INTERSECTOR
+static ArtSVP *
+art_svp_merge_perturbed (const ArtSVP *svp1, const ArtSVP *svp2)
+{
+ ArtVpath *vpath1, *vpath2;
+ ArtVpath *vpath1_p, *vpath2_p;
+ ArtSVP *svp1_p, *svp2_p;
+ ArtSVP *svp_new;
+
+ vpath1 = art_vpath_from_svp (svp1);
+ vpath1_p = art_vpath_perturb (vpath1);
+ art_free (vpath1);
+ svp1_p = art_svp_from_vpath (vpath1_p);
+ art_free (vpath1_p);
+
+ vpath2 = art_vpath_from_svp (svp2);
+ vpath2_p = art_vpath_perturb (vpath2);
+ art_free (vpath2);
+ svp2_p = art_svp_from_vpath (vpath2_p);
+ art_free (vpath2_p);
+
+ svp_new = art_svp_merge (svp1_p, svp2_p);
+#ifdef VERBOSE
+ print_ps_svp (svp1_p);
+ print_ps_svp (svp2_p);
+ print_ps_svp (svp_new);
+#endif
+ art_free (svp1_p);
+ art_free (svp2_p);
+
+ return svp_new;
+}
+#endif
+
+/* Compute the union of two vector paths.
+
+ Status of this routine:
+
+ Basic correctness: Seems to work.
+
+ Numerical stability: We cheat (adding random perturbation). Thus,
+ it seems very likely that no numerical stability problems will be
+ seen in practice.
+
+ Speed: Would be better if we didn't go to unsorted vector path
+ and back to add the perturbation.
+
+ Precision: The perturbation fuzzes the coordinates slightly. In
+ cases of butting segments, razor thin long holes may appear.
+
+*/
+/**
+ * art_svp_union: Compute the union of two sorted vector paths.
+ * @svp1: One sorted vector path.
+ * @svp2: The other sorted vector path.
+ *
+ * Computes the union of the two argument svp's. Given two svp's with
+ * winding numbers of 0 and 1 everywhere, the resulting winding number
+ * will be 1 where either (or both) of the argument svp's has a
+ * winding number 1, 0 otherwise. The result is newly allocated.
+ *
+ * Currently, this routine has accuracy problems pending the
+ * implementation of the new intersector.
+ *
+ * Return value: The union of @svp1 and @svp2.
+ **/
+ArtSVP *
+art_svp_union (const ArtSVP *svp1, const ArtSVP *svp2)
+{
+#ifdef ART_USE_NEW_INTERSECTOR
+ ArtSVP *svp3, *svp_new;
+ ArtSvpWriter *swr;
+
+ svp3 = art_svp_merge (svp1, svp2);
+ swr = art_svp_writer_rewind_new (ART_WIND_RULE_POSITIVE);
+ art_svp_intersector (svp3, swr);
+ svp_new = art_svp_writer_rewind_reap (swr);
+ art_free (svp3); /* shallow free because svp3 contains shared segments */
+
+ return svp_new;
+#else
+ ArtSVP *svp3, *svp4, *svp_new;
+
+ svp3 = art_svp_merge_perturbed (svp1, svp2);
+ svp4 = art_svp_uncross (svp3);
+ art_svp_free (svp3);
+
+ svp_new = art_svp_rewind_uncrossed (svp4, ART_WIND_RULE_POSITIVE);
+#ifdef VERBOSE
+ print_ps_svp (svp4);
+ print_ps_svp (svp_new);
+#endif
+ art_svp_free (svp4);
+ return svp_new;
+#endif
+}
+
+/* Compute the intersection of two vector paths.
+
+ Status of this routine:
+
+ Basic correctness: Seems to work.
+
+ Numerical stability: We cheat (adding random perturbation). Thus,
+ it seems very likely that no numerical stability problems will be
+ seen in practice.
+
+ Speed: Would be better if we didn't go to unsorted vector path
+ and back to add the perturbation.
+
+ Precision: The perturbation fuzzes the coordinates slightly. In
+ cases of butting segments, razor thin long isolated segments may
+ appear.
+
+*/
+
+/**
+ * art_svp_intersect: Compute the intersection of two sorted vector paths.
+ * @svp1: One sorted vector path.
+ * @svp2: The other sorted vector path.
+ *
+ * Computes the intersection of the two argument svp's. Given two
+ * svp's with winding numbers of 0 and 1 everywhere, the resulting
+ * winding number will be 1 where both of the argument svp's has a
+ * winding number 1, 0 otherwise. The result is newly allocated.
+ *
+ * Currently, this routine has accuracy problems pending the
+ * implementation of the new intersector.
+ *
+ * Return value: The intersection of @svp1 and @svp2.
+ **/
+ArtSVP *
+art_svp_intersect (const ArtSVP *svp1, const ArtSVP *svp2)
+{
+#ifdef ART_USE_NEW_INTERSECTOR
+ ArtSVP *svp3, *svp_new;
+ ArtSvpWriter *swr;
+
+ svp3 = art_svp_merge (svp1, svp2);
+ swr = art_svp_writer_rewind_new (ART_WIND_RULE_INTERSECT);
+ art_svp_intersector (svp3, swr);
+ svp_new = art_svp_writer_rewind_reap (swr);
+ art_free (svp3); /* shallow free because svp3 contains shared segments */
+
+ return svp_new;
+#else
+ ArtSVP *svp3, *svp4, *svp_new;
+
+ svp3 = art_svp_merge_perturbed (svp1, svp2);
+ svp4 = art_svp_uncross (svp3);
+ art_svp_free (svp3);
+
+ svp_new = art_svp_rewind_uncrossed (svp4, ART_WIND_RULE_INTERSECT);
+ art_svp_free (svp4);
+ return svp_new;
+#endif
+}
+
+/* Compute the symmetric difference of two vector paths.
+
+ Status of this routine:
+
+ Basic correctness: Seems to work.
+
+ Numerical stability: We cheat (adding random perturbation). Thus,
+ it seems very likely that no numerical stability problems will be
+ seen in practice.
+
+ Speed: We could do a lot better by scanning through the svp
+ representations and culling out any segments that are exactly
+ identical. It would also be better if we didn't go to unsorted
+ vector path and back to add the perturbation.
+
+ Precision: Awful. In the case of inputs which are similar (the
+ common case for canvas display), the entire outline is "hairy." In
+ addition, the perturbation fuzzes the coordinates slightly. It can
+ be used as a conservative approximation.
+
+*/
+
+/**
+ * art_svp_diff: Compute the symmetric difference of two sorted vector paths.
+ * @svp1: One sorted vector path.
+ * @svp2: The other sorted vector path.
+ *
+ * Computes the symmetric of the two argument svp's. Given two svp's
+ * with winding numbers of 0 and 1 everywhere, the resulting winding
+ * number will be 1 where either, but not both, of the argument svp's
+ * has a winding number 1, 0 otherwise. The result is newly allocated.
+ *
+ * Currently, this routine has accuracy problems pending the
+ * implementation of the new intersector.
+ *
+ * Return value: The symmetric difference of @svp1 and @svp2.
+ **/
+ArtSVP *
+art_svp_diff (const ArtSVP *svp1, const ArtSVP *svp2)
+{
+#ifdef ART_USE_NEW_INTERSECTOR
+ ArtSVP *svp3, *svp_new;
+ ArtSvpWriter *swr;
+
+ svp3 = art_svp_merge (svp1, svp2);
+ swr = art_svp_writer_rewind_new (ART_WIND_RULE_ODDEVEN);
+ art_svp_intersector (svp3, swr);
+ svp_new = art_svp_writer_rewind_reap (swr);
+ art_free (svp3); /* shallow free because svp3 contains shared segments */
+
+ return svp_new;
+#else
+ ArtSVP *svp3, *svp4, *svp_new;
+
+ svp3 = art_svp_merge_perturbed (svp1, svp2);
+ svp4 = art_svp_uncross (svp3);
+ art_svp_free (svp3);
+
+ svp_new = art_svp_rewind_uncrossed (svp4, ART_WIND_RULE_ODDEVEN);
+ art_svp_free (svp4);
+ return svp_new;
+#endif
+}
+
+#ifdef ART_USE_NEW_INTERSECTOR
+ArtSVP *
+art_svp_minus (const ArtSVP *svp1, const ArtSVP *svp2)
+{
+ ArtSVP *svp2_mod;
+ ArtSVP *svp3, *svp_new;
+ ArtSvpWriter *swr;
+ int i;
+
+ svp2_mod = (ArtSVP *) svp2; /* get rid of the const for a while */
+
+ /* First invert svp2 to "turn it inside out" */
+ for (i = 0; i < svp2_mod->n_segs; i++)
+ svp2_mod->segs[i].dir = !svp2_mod->segs[i].dir;
+
+ svp3 = art_svp_merge (svp1, svp2_mod);
+ swr = art_svp_writer_rewind_new (ART_WIND_RULE_POSITIVE);
+ art_svp_intersector (svp3, swr);
+ svp_new = art_svp_writer_rewind_reap (swr);
+ art_free (svp3); /* shallow free because svp3 contains shared segments */
+
+ /* Flip svp2 back to its original state */
+ for (i = 0; i < svp2_mod->n_segs; i++)
+ svp2_mod->segs[i].dir = !svp2_mod->segs[i].dir;
+
+ return svp_new;
+}
+#endif /* ART_USE_NEW_INTERSECTOR */
diff -Nru swftools-0.9.2+ds1/lib/art/art_svp_ops.h swftools-0.9.1/lib/art/art_svp_ops.h
--- swftools-0.9.2+ds1/lib/art/art_svp_ops.h 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/art/art_svp_ops.h 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,46 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __ART_SVP_OPS_H__
+#define __ART_SVP_OPS_H__
+
+#ifdef LIBART_COMPILATION
+#include "art_svp.h"
+#else
+#include "art_svp.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/* Vector path set operations, over sorted vpaths. */
+
+ArtSVP *art_svp_union (const ArtSVP *svp1, const ArtSVP *svp2);
+ArtSVP *art_svp_intersect (const ArtSVP *svp1, const ArtSVP *svp2);
+ArtSVP *art_svp_diff (const ArtSVP *svp1, const ArtSVP *svp2);
+ArtSVP *art_svp_minus (const ArtSVP *svp1, const ArtSVP *svp2);
+
+ArtSVP *art_svp_merge (const ArtSVP *svp1, const ArtSVP *svp2);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __ART_SVP_OPS_H__ */
diff -Nru swftools-0.9.2+ds1/lib/art/art_svp_point.c swftools-0.9.1/lib/art/art_svp_point.c
--- swftools-0.9.2+ds1/lib/art/art_svp_point.c 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/art/art_svp_point.c 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,144 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1999 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+#include "art_svp_point.h"
+
+#include
+#include "art_misc.h"
+
+#include "art_svp.h"
+
+/* Determine whether a point is inside, or near, an svp. */
+
+/* return winding number of point wrt svp */
+/**
+ * art_svp_point_wind: Determine winding number of a point with respect to svp.
+ * @svp: The svp.
+ * @x: The X coordinate of the point.
+ * @y: The Y coordinate of the point.
+ *
+ * Determine the winding number of the point @x, @y with respect to @svp.
+ *
+ * Return value: the winding number.
+ **/
+int
+art_svp_point_wind (ArtSVP *svp, double x, double y)
+{
+ int i, j;
+ int wind = 0;
+
+ for (i = 0; i < svp->n_segs; i++)
+ {
+ ArtSVPSeg *seg = &svp->segs[i];
+
+ if (seg->bbox.y0 > y)
+ break;
+
+ if (seg->bbox.y1 > y)
+ {
+ if (seg->bbox.x1 < x)
+ wind += seg->dir ? 1 : -1;
+ else if (seg->bbox.x0 <= x)
+ {
+ double x0, y0, x1, y1, dx, dy;
+
+ for (j = 0; j < seg->n_points - 1; j++)
+ {
+ if (seg->points[j + 1].y > y)
+ break;
+ }
+ x0 = seg->points[j].x;
+ y0 = seg->points[j].y;
+ x1 = seg->points[j + 1].x;
+ y1 = seg->points[j + 1].y;
+
+ dx = x1 - x0;
+ dy = y1 - y0;
+ if ((x - x0) * dy > (y - y0) * dx)
+ wind += seg->dir ? 1 : -1;
+ }
+ }
+ }
+
+ return wind;
+}
+
+/**
+ * art_svp_point_dist: Determine distance between point and svp.
+ * @svp: The svp.
+ * @x: The X coordinate of the point.
+ * @y: The Y coordinate of the point.
+ *
+ * Determines the distance of the point @x, @y to the closest edge in
+ * @svp. A large number is returned if @svp is empty.
+ *
+ * Return value: the distance.
+ **/
+double
+art_svp_point_dist (ArtSVP *svp, double x, double y)
+{
+ int i, j;
+ double dist_sq;
+ double best_sq = -1;
+
+ for (i = 0; i < svp->n_segs; i++)
+ {
+ ArtSVPSeg *seg = &svp->segs[i];
+ for (j = 0; j < seg->n_points - 1; j++)
+ {
+ double x0 = seg->points[j].x;
+ double y0 = seg->points[j].y;
+ double x1 = seg->points[j + 1].x;
+ double y1 = seg->points[j + 1].y;
+
+ double dx = x1 - x0;
+ double dy = y1 - y0;
+
+ double dxx0 = x - x0;
+ double dyy0 = y - y0;
+
+ double dot = dxx0 * dx + dyy0 * dy;
+
+ if (dot < 0)
+ dist_sq = dxx0 * dxx0 + dyy0 * dyy0;
+ else
+ {
+ double rr = dx * dx + dy * dy;
+
+ if (dot > rr)
+ dist_sq = (x - x1) * (x - x1) + (y - y1) * (y - y1);
+ else
+ {
+ double perp = (y - y0) * dx - (x - x0) * dy;
+
+ dist_sq = perp * perp / rr;
+ }
+ }
+ if (best_sq < 0 || dist_sq < best_sq)
+ best_sq = dist_sq;
+ }
+ }
+
+ if (best_sq >= 0)
+ return sqrt (best_sq);
+ else
+ return 1e12;
+}
+
diff -Nru swftools-0.9.2+ds1/lib/art/art_svp_point.h swftools-0.9.1/lib/art/art_svp_point.h
--- swftools-0.9.2+ds1/lib/art/art_svp_point.h 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/art/art_svp_point.h 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,49 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1999 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __ART_SVP_POINT_H__
+#define __ART_SVP_POINT_H__
+
+/* Determine whether a point is inside, or near, an svp. */
+
+#ifdef LIBART_COMPILATION
+#include "art_svp.h"
+#else
+#include "art_svp.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+int
+art_svp_point_wind (ArtSVP *svp, double x, double y);
+
+double
+art_svp_point_dist (ArtSVP *svp, double x, double y);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __ART_SVP_H__ */
+
+
+
+
diff -Nru swftools-0.9.2+ds1/lib/art/art_svp_render_aa.c swftools-0.9.1/lib/art/art_svp_render_aa.c
--- swftools-0.9.2+ds1/lib/art/art_svp_render_aa.c 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/art/art_svp_render_aa.c 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,463 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998-2000 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/* The spiffy antialiased renderer for sorted vector paths. */
+
+#include "config.h"
+#include "art_svp_render_aa.h"
+
+#include
+#include /* for memmove */
+#include "art_misc.h"
+
+#include "art_rect.h"
+#include "art_svp.h"
+
+#include
+
+typedef double artfloat;
+
+struct _ArtSVPRenderAAIter {
+ const ArtSVP *svp;
+ int x0, x1;
+ int y;
+ int seg_ix;
+
+ int *active_segs;
+ int n_active_segs;
+ int *cursor;
+ artfloat *seg_x;
+ artfloat *seg_dx;
+
+ ArtSVPRenderAAStep *steps;
+};
+
+static void
+art_svp_render_insert_active (int i, int *active_segs, int n_active_segs,
+ artfloat *seg_x, artfloat *seg_dx)
+{
+ int j;
+ artfloat x;
+ int tmp1, tmp2;
+
+ /* this is a cheap hack to get ^'s sorted correctly */
+ x = seg_x[i] + 0.001 * seg_dx[i];
+ for (j = 0; j < n_active_segs && seg_x[active_segs[j]] < x; j++);
+
+ tmp1 = i;
+ while (j < n_active_segs)
+ {
+ tmp2 = active_segs[j];
+ active_segs[j] = tmp1;
+ tmp1 = tmp2;
+ j++;
+ }
+ active_segs[j] = tmp1;
+}
+
+static void
+art_svp_render_delete_active (int *active_segs, int j, int n_active_segs)
+{
+ int k;
+
+ for (k = j; k < n_active_segs; k++)
+ active_segs[k] = active_segs[k + 1];
+}
+
+#define EPSILON 1e-6
+
+/* Render the sorted vector path in the given rectangle, antialiased.
+
+ This interface uses a callback for the actual pixel rendering. The
+ callback is called y1 - y0 times (once for each scan line). The y
+ coordinate is given as an argument for convenience (it could be
+ stored in the callback's private data and incremented on each
+ call).
+
+ The rendered polygon is represented in a semi-runlength format: a
+ start value and a sequence of "steps". Each step has an x
+ coordinate and a value delta. The resulting value at position x is
+ equal to the sum of the start value and all step delta values for
+ which the step x coordinate is less than or equal to x. An
+ efficient algorithm will traverse the steps left to right, keeping
+ a running sum.
+
+ All x coordinates in the steps are guaranteed to be x0 <= x < x1.
+ (This guarantee is a change from the gfonted vpaar renderer, and is
+ designed to simplify the callback).
+
+ There is now a further guarantee that no two steps will have the
+ same x value. This may allow for further speedup and simplification
+ of renderers.
+
+ The value 0x8000 represents 0% coverage by the polygon, while
+ 0xff8000 represents 100% coverage. This format is designed so that
+ >> 16 results in a standard 0x00..0xff value range, with nice
+ rounding.
+
+ Status of this routine:
+
+ Basic correctness: OK
+
+ Numerical stability: pretty good, although probably not
+ bulletproof.
+
+ Speed: Needs more aggressive culling of bounding boxes. Can
+ probably speed up the [x0,x1) clipping of step values. Can do more
+ of the step calculation in fixed point.
+
+ Precision: No known problems, although it should be tested
+ thoroughly, especially for symmetry.
+
+*/
+
+ArtSVPRenderAAIter *
+art_svp_render_aa_iter (const ArtSVP *svp,
+ int x0, int y0, int x1, int y1)
+{
+ ArtSVPRenderAAIter *iter = art_new (ArtSVPRenderAAIter, 1);
+
+ iter->svp = svp;
+ iter->y = y0;
+ iter->x0 = x0;
+ iter->x1 = x1;
+ iter->seg_ix = 0;
+
+ iter->active_segs = art_new (int, svp->n_segs);
+ iter->cursor = art_new (int, svp->n_segs);
+ iter->seg_x = art_new (artfloat, svp->n_segs);
+ iter->seg_dx = art_new (artfloat, svp->n_segs);
+ iter->steps = art_new (ArtSVPRenderAAStep, x1 - x0);
+ iter->n_active_segs = 0;
+
+ return iter;
+}
+
+#define ADD_STEP(xpos, xdelta) \
+ /* stereotype code fragment for adding a step */ \
+ if (n_steps == 0 || steps[n_steps - 1].x < xpos) \
+ { \
+ sx = n_steps; \
+ steps[sx].x = xpos; \
+ steps[sx].delta = xdelta; \
+ n_steps++; \
+ } \
+ else \
+ { \
+ for (sx = n_steps; sx > 0; sx--) \
+ { \
+ if (steps[sx - 1].x == xpos) \
+ { \
+ steps[sx - 1].delta += xdelta; \
+ sx = n_steps; \
+ break; \
+ } \
+ else if (steps[sx - 1].x < xpos) \
+ { \
+ break; \
+ } \
+ } \
+ if (sx < n_steps) \
+ { \
+ memmove (&steps[sx + 1], &steps[sx], \
+ (n_steps - sx) * sizeof(steps[0])); \
+ steps[sx].x = xpos; \
+ steps[sx].delta = xdelta; \
+ n_steps++; \
+ } \
+ }
+
+void
+art_svp_render_aa_iter_step (ArtSVPRenderAAIter *iter, int *p_start,
+ ArtSVPRenderAAStep **p_steps, int *p_n_steps)
+{
+ const ArtSVP *svp = iter->svp;
+ int *active_segs = iter->active_segs;
+ int n_active_segs = iter->n_active_segs;
+ int *cursor = iter->cursor;
+ artfloat *seg_x = iter->seg_x;
+ artfloat *seg_dx = iter->seg_dx;
+ int i = iter->seg_ix;
+ int j;
+ int x0 = iter->x0;
+ int x1 = iter->x1;
+ int y = iter->y;
+ int seg_index;
+
+ int x;
+ ArtSVPRenderAAStep *steps = iter->steps;
+ int n_steps;
+ artfloat y_top, y_bot;
+ artfloat x_top, x_bot;
+ artfloat x_min, x_max;
+ int ix_min, ix_max;
+ artfloat delta; /* delta should be int too? */
+ int last, xthis;
+ int xdelta;
+ artfloat rslope, drslope;
+ int start;
+ const ArtSVPSeg *seg;
+ int curs;
+ artfloat dy;
+
+ int sx;
+
+ /* insert new active segments */
+ for (; i < svp->n_segs && svp->segs[i].bbox.y0 < y + 1; i++)
+ {
+ if (svp->segs[i].bbox.y1 > y &&
+ svp->segs[i].bbox.x0 < x1)
+ {
+ seg = &svp->segs[i];
+ /* move cursor to topmost vector which overlaps [y,y+1) */
+ for (curs = 0; seg->points[curs + 1].y < y; curs++);
+ cursor[i] = curs;
+ dy = seg->points[curs + 1].y - seg->points[curs].y;
+ if (fabs (dy) >= EPSILON)
+ seg_dx[i] = (seg->points[curs + 1].x - seg->points[curs].x) /
+ dy;
+ else
+ seg_dx[i] = 1e12;
+ seg_x[i] = seg->points[curs].x +
+ (y - seg->points[curs].y) * seg_dx[i];
+ art_svp_render_insert_active (i, active_segs, n_active_segs++,
+ seg_x, seg_dx);
+ }
+ }
+
+ n_steps = 0;
+
+ /* render the runlengths, advancing and deleting as we go */
+ start = 0x8000;
+
+ for (j = 0; j < n_active_segs; j++)
+ {
+ seg_index = active_segs[j];
+ seg = &svp->segs[seg_index];
+ curs = cursor[seg_index];
+ while (curs != seg->n_points - 1 &&
+ seg->points[curs].y < y + 1)
+ {
+ y_top = y;
+ if (y_top < seg->points[curs].y)
+ y_top = seg->points[curs].y;
+ y_bot = y + 1;
+ if (y_bot > seg->points[curs + 1].y)
+ y_bot = seg->points[curs + 1].y;
+ if (y_top != y_bot) {
+ delta = (seg->dir ? 16711680.0 : -16711680.0) *
+ (y_bot - y_top);
+ x_top = seg_x[seg_index] + (y_top - y) * seg_dx[seg_index];
+ x_bot = seg_x[seg_index] + (y_bot - y) * seg_dx[seg_index];
+ if (x_top < x_bot)
+ {
+ x_min = x_top;
+ x_max = x_bot;
+ }
+ else
+ {
+ x_min = x_bot;
+ x_max = x_top;
+ }
+ ix_min = floor (x_min);
+ ix_max = floor (x_max);
+ if (ix_min >= x1)
+ {
+ /* skip; it starts to the right of the render region */
+ }
+ else if (ix_max < x0)
+ /* it ends to the left of the render region */
+ start += delta;
+ else if (ix_min == ix_max)
+ {
+ /* case 1, antialias a single pixel */
+ xdelta = (ix_min + 1 - (x_min + x_max) * 0.5) * delta;
+
+ ADD_STEP(ix_min, xdelta)
+
+ if (ix_min + 1 < x1)
+ {
+ xdelta = delta - xdelta;
+
+ ADD_STEP(ix_min + 1, xdelta)
+ }
+ }
+ else
+ {
+ /* case 2, antialias a run */
+ rslope = 1.0 / fabs (seg_dx[seg_index]);
+ drslope = delta * rslope;
+ last =
+ drslope * 0.5 *
+ (ix_min + 1 - x_min) * (ix_min + 1 - x_min);
+ xdelta = last;
+ if (ix_min >= x0)
+ {
+ ADD_STEP(ix_min, xdelta)
+
+ x = ix_min + 1;
+ }
+ else
+ {
+ start += last;
+ x = x0;
+ }
+ if (ix_max > x1)
+ ix_max = x1;
+ for (; x < ix_max; x++)
+ {
+ xthis = (seg->dir ? 16711680.0 : -16711680.0) * rslope *
+ (x + 0.5 - x_min);
+ xdelta = xthis - last;
+ last = xthis;
+
+ ADD_STEP(x, xdelta)
+ }
+ if (x < x1)
+ {
+ xthis =
+ delta * (1 - 0.5 *
+ (x_max - ix_max) * (x_max - ix_max) *
+ rslope);
+ xdelta = xthis - last;
+ last = xthis;
+
+ ADD_STEP(x, xdelta)
+
+ if (x + 1 < x1)
+ {
+ xdelta = delta - last;
+
+ ADD_STEP(x + 1, xdelta)
+ }
+ }
+ }
+ }
+ curs++;
+ if (curs != seg->n_points - 1 &&
+ seg->points[curs].y < y + 1)
+ {
+ dy = seg->points[curs + 1].y - seg->points[curs].y;
+ if (fabs (dy) >= EPSILON)
+ seg_dx[seg_index] = (seg->points[curs + 1].x -
+ seg->points[curs].x) / dy;
+ else
+ seg_dx[seg_index] = 1e12;
+ seg_x[seg_index] = seg->points[curs].x +
+ (y - seg->points[curs].y) * seg_dx[seg_index];
+ }
+ /* break here, instead of duplicating predicate in while? */
+ }
+ if (seg->points[curs].y >= y + 1)
+ {
+ curs--;
+ cursor[seg_index] = curs;
+ seg_x[seg_index] += seg_dx[seg_index];
+ }
+ else
+ {
+ art_svp_render_delete_active (active_segs, j--,
+ --n_active_segs);
+ }
+ }
+
+ *p_start = start;
+ *p_steps = steps;
+ *p_n_steps = n_steps;
+
+ iter->seg_ix = i;
+ iter->n_active_segs = n_active_segs;
+ iter->y++;
+}
+
+void
+art_svp_render_aa_iter_done (ArtSVPRenderAAIter *iter)
+{
+ art_free (iter->steps);
+
+ art_free (iter->seg_dx);
+ art_free (iter->seg_x);
+ art_free (iter->cursor);
+ art_free (iter->active_segs);
+ art_free (iter);
+}
+
+/**
+ * art_svp_render_aa: Render SVP antialiased.
+ * @svp: The #ArtSVP to render.
+ * @x0: Left coordinate of destination rectangle.
+ * @y0: Top coordinate of destination rectangle.
+ * @x1: Right coordinate of destination rectangle.
+ * @y1: Bottom coordinate of destination rectangle.
+ * @callback: The callback which actually paints the pixels.
+ * @callback_data: Private data for @callback.
+ *
+ * Renders the sorted vector path in the given rectangle, antialiased.
+ *
+ * This interface uses a callback for the actual pixel rendering. The
+ * callback is called @y1 - @y0 times (once for each scan line). The y
+ * coordinate is given as an argument for convenience (it could be
+ * stored in the callback's private data and incremented on each
+ * call).
+ *
+ * The rendered polygon is represented in a semi-runlength format: a
+ * start value and a sequence of "steps". Each step has an x
+ * coordinate and a value delta. The resulting value at position x is
+ * equal to the sum of the start value and all step delta values for
+ * which the step x coordinate is less than or equal to x. An
+ * efficient algorithm will traverse the steps left to right, keeping
+ * a running sum.
+ *
+ * All x coordinates in the steps are guaranteed to be @x0 <= x < @x1.
+ * (This guarantee is a change from the gfonted vpaar renderer from
+ * which this routine is derived, and is designed to simplify the
+ * callback).
+ *
+ * The value 0x8000 represents 0% coverage by the polygon, while
+ * 0xff8000 represents 100% coverage. This format is designed so that
+ * >> 16 results in a standard 0x00..0xff value range, with nice
+ * rounding.
+ *
+ **/
+void
+art_svp_render_aa (const ArtSVP *svp,
+ int x0, int y0, int x1, int y1,
+ void (*callback) (void *callback_data,
+ int y,
+ int start,
+ ArtSVPRenderAAStep *steps, int n_steps),
+ void *callback_data)
+{
+ ArtSVPRenderAAIter *iter;
+ int y;
+ int start;
+ ArtSVPRenderAAStep *steps;
+ int n_steps;
+
+ iter = art_svp_render_aa_iter (svp, x0, y0, x1, y1);
+
+
+ for (y = y0; y < y1; y++)
+ {
+ art_svp_render_aa_iter_step (iter, &start, &steps, &n_steps);
+ (*callback) (callback_data, y, start, steps, n_steps);
+ }
+
+ art_svp_render_aa_iter_done (iter);
+}
diff -Nru swftools-0.9.2+ds1/lib/art/art_svp_render_aa.h swftools-0.9.1/lib/art/art_svp_render_aa.h
--- swftools-0.9.2+ds1/lib/art/art_svp_render_aa.h 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/art/art_svp_render_aa.h 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,67 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __ART_SVP_RENDER_AA_H__
+#define __ART_SVP_RENDER_AA_H__
+
+/* The spiffy antialiased renderer for sorted vector paths. */
+
+#ifdef LIBART_COMPILATION
+#include "art_svp.h"
+#else
+#include "art_svp.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+typedef struct _ArtSVPRenderAAStep ArtSVPRenderAAStep;
+typedef struct _ArtSVPRenderAAIter ArtSVPRenderAAIter;
+
+struct _ArtSVPRenderAAStep {
+ int x;
+ int delta; /* stored with 16 fractional bits */
+};
+
+ArtSVPRenderAAIter *
+art_svp_render_aa_iter (const ArtSVP *svp,
+ int x0, int y0, int x1, int y1);
+
+void
+art_svp_render_aa_iter_step (ArtSVPRenderAAIter *iter, int *p_start,
+ ArtSVPRenderAAStep **p_steps, int *p_n_steps);
+
+void
+art_svp_render_aa_iter_done (ArtSVPRenderAAIter *iter);
+
+void
+art_svp_render_aa (const ArtSVP *svp,
+ int x0, int y0, int x1, int y1,
+ void (*callback) (void *callback_data,
+ int y,
+ int start,
+ ArtSVPRenderAAStep *steps, int n_steps),
+ void *callback_data);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __ART_SVP_RENDER_AA_H__ */
diff -Nru swftools-0.9.2+ds1/lib/art/art_svp_vpath.c swftools-0.9.1/lib/art/art_svp_vpath.c
--- swftools-0.9.2+ds1/lib/art/art_svp_vpath.c 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/art/art_svp_vpath.c 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,215 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998-2000 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/* Sort vector paths into sorted vector paths */
+
+#include "config.h"
+#include "art_svp_vpath.h"
+
+#include
+#include
+
+#include "art_misc.h"
+
+#include "art_vpath.h"
+#include "art_svp.h"
+
+
+/* reverse a list of points in place */
+static void
+reverse_points (ArtPoint *points, int n_points)
+{
+ int i;
+ ArtPoint tmp_p;
+
+ for (i = 0; i < (n_points >> 1); i++)
+ {
+ tmp_p = points[i];
+ points[i] = points[n_points - (i + 1)];
+ points[n_points - (i + 1)] = tmp_p;
+ }
+}
+
+/**
+ * art_svp_from_vpath: Convert a vpath to a sorted vector path.
+ * @vpath: #ArtVPath to convert.
+ *
+ * Converts a vector path into sorted vector path form. The svp form is
+ * more efficient for rendering and other vector operations.
+ *
+ * Basically, the implementation is to traverse the vector path,
+ * generating a new segment for each "run" of points in the vector
+ * path with monotonically increasing Y values. All the resulting
+ * values are then sorted.
+ *
+ * Note: I'm not sure that the sorting rule is correct with respect
+ * to numerical stability issues.
+ *
+ * Return value: Resulting sorted vector path.
+ **/
+ArtSVP *
+art_svp_from_vpath (ArtVpath *vpath)
+{
+ int n_segs, n_segs_max;
+ ArtSVP *svp;
+ int dir;
+ int new_dir;
+ int i;
+ ArtPoint *points;
+ int n_points, n_points_max;
+ double x, y;
+ double x_min, x_max;
+
+ n_segs = 0;
+ n_segs_max = 16;
+ svp = (ArtSVP *)art_alloc (sizeof(ArtSVP) +
+ (n_segs_max - 1) * sizeof(ArtSVPSeg));
+
+ dir = 0;
+ n_points = 0;
+ n_points_max = 0;
+ points = NULL;
+ i = 0;
+
+ x = y = 0; /* unnecessary, given "first code must not be LINETO" invariant,
+ but it makes gcc -Wall -ansi -pedantic happier */
+ x_min = x_max = 0; /* same */
+
+ while (vpath[i].code != ART_END) {
+ if (vpath[i].code == ART_MOVETO || vpath[i].code == ART_MOVETO_OPEN)
+ {
+ if (points != NULL && n_points >= 2)
+ {
+ if (n_segs == n_segs_max)
+ {
+ n_segs_max <<= 1;
+ svp = (ArtSVP *)art_realloc (svp, sizeof(ArtSVP) +
+ (n_segs_max - 1) *
+ sizeof(ArtSVPSeg));
+ }
+ svp->segs[n_segs].n_points = n_points;
+ svp->segs[n_segs].dir = (dir > 0);
+ if (dir < 0)
+ reverse_points (points, n_points);
+ svp->segs[n_segs].points = points;
+ svp->segs[n_segs].bbox.x0 = x_min;
+ svp->segs[n_segs].bbox.x1 = x_max;
+ svp->segs[n_segs].bbox.y0 = points[0].y;
+ svp->segs[n_segs].bbox.y1 = points[n_points - 1].y;
+ n_segs++;
+ points = NULL;
+ }
+
+ if (points == NULL)
+ {
+ n_points_max = 4;
+ points = art_new (ArtPoint, n_points_max);
+ }
+
+ n_points = 1;
+ points[0].x = x = vpath[i].x;
+ points[0].y = y = vpath[i].y;
+ x_min = x;
+ x_max = x;
+ dir = 0;
+ }
+ else /* must be LINETO */
+ {
+ new_dir = (vpath[i].y > y ||
+ (vpath[i].y == y && vpath[i].x > x)) ? 1 : -1;
+ if (dir && dir != new_dir)
+ {
+ /* new segment */
+ x = points[n_points - 1].x;
+ y = points[n_points - 1].y;
+ if (n_segs == n_segs_max)
+ {
+ n_segs_max <<= 1;
+ svp = (ArtSVP *)art_realloc (svp, sizeof(ArtSVP) +
+ (n_segs_max - 1) *
+ sizeof(ArtSVPSeg));
+ }
+ svp->segs[n_segs].n_points = n_points;
+ svp->segs[n_segs].dir = (dir > 0);
+ if (dir < 0)
+ reverse_points (points, n_points);
+ svp->segs[n_segs].points = points;
+ svp->segs[n_segs].bbox.x0 = x_min;
+ svp->segs[n_segs].bbox.x1 = x_max;
+ svp->segs[n_segs].bbox.y0 = points[0].y;
+ svp->segs[n_segs].bbox.y1 = points[n_points - 1].y;
+ n_segs++;
+
+ n_points = 1;
+ n_points_max = 4;
+ points = art_new (ArtPoint, n_points_max);
+ points[0].x = x;
+ points[0].y = y;
+ x_min = x;
+ x_max = x;
+ }
+
+ if (points != NULL)
+ {
+ if (n_points == n_points_max)
+ art_expand (points, ArtPoint, n_points_max);
+ points[n_points].x = x = vpath[i].x;
+ points[n_points].y = y = vpath[i].y;
+ if (x < x_min) x_min = x;
+ else if (x > x_max) x_max = x;
+ n_points++;
+ }
+ dir = new_dir;
+ }
+ i++;
+ }
+
+ if (points != NULL)
+ {
+ if (n_points >= 2)
+ {
+ if (n_segs == n_segs_max)
+ {
+ n_segs_max <<= 1;
+ svp = (ArtSVP *)art_realloc (svp, sizeof(ArtSVP) +
+ (n_segs_max - 1) *
+ sizeof(ArtSVPSeg));
+ }
+ svp->segs[n_segs].n_points = n_points;
+ svp->segs[n_segs].dir = (dir > 0);
+ if (dir < 0)
+ reverse_points (points, n_points);
+ svp->segs[n_segs].points = points;
+ svp->segs[n_segs].bbox.x0 = x_min;
+ svp->segs[n_segs].bbox.x1 = x_max;
+ svp->segs[n_segs].bbox.y0 = points[0].y;
+ svp->segs[n_segs].bbox.y1 = points[n_points - 1].y;
+ n_segs++;
+ }
+ else
+ art_free (points);
+ }
+
+ svp->n_segs = n_segs;
+
+ qsort (&svp->segs, n_segs, sizeof (ArtSVPSeg), art_svp_seg_compare);
+
+ return svp;
+}
+
diff -Nru swftools-0.9.2+ds1/lib/art/art_svp_vpath.h swftools-0.9.1/lib/art/art_svp_vpath.h
--- swftools-0.9.2+ds1/lib/art/art_svp_vpath.h 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/art/art_svp_vpath.h 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,44 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __ART_SVP_VPATH_H__
+#define __ART_SVP_VPATH_H__
+
+#ifdef LIBART_COMPILATION
+#include "art_svp.h"
+#include "art_vpath.h"
+#else
+#include "art_svp.h"
+#include "art_vpath.h"
+#endif
+
+/* Sort vector paths into sorted vector paths. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+ArtSVP *
+art_svp_from_vpath (ArtVpath *vpath);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __ART_SVP_VPATH_H__ */
diff -Nru swftools-0.9.2+ds1/lib/art/art_svp_vpath_stroke.c swftools-0.9.1/lib/art/art_svp_vpath_stroke.c
--- swftools-0.9.2+ds1/lib/art/art_svp_vpath_stroke.c 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/art/art_svp_vpath_stroke.c 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,741 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998-2000 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+
+#include "config.h"
+#include "art_svp_vpath_stroke.h"
+
+#include
+#include
+
+#include "art_misc.h"
+
+#include "art_vpath.h"
+#include "art_svp.h"
+#ifdef ART_USE_NEW_INTERSECTOR
+#include "art_svp_intersect.h"
+#else
+#include "art_svp_wind.h"
+#endif
+#include "art_svp_vpath.h"
+
+#define EPSILON 1e-6
+#define EPSILON_2 1e-12
+
+#define yes_OPTIMIZE_INNER
+
+/* Render an arc segment starting at (xc + x0, yc + y0) to (xc + x1,
+ yc + y1), centered at (xc, yc), and with given radius. Both x0^2 +
+ y0^2 and x1^2 + y1^2 should be equal to radius^2.
+
+ A positive value of radius means curve to the left, negative means
+ curve to the right.
+*/
+static void
+art_svp_vpath_stroke_arc (ArtVpath **p_vpath, int *pn, int *pn_max,
+ double xc, double yc,
+ double x0, double y0,
+ double x1, double y1,
+ double radius,
+ double flatness)
+{
+ double theta;
+ double th_0, th_1;
+ int n_pts;
+ int i;
+ double aradius;
+
+ aradius = fabs (radius);
+ theta = 2 * M_SQRT2 * sqrt (flatness / aradius);
+ th_0 = atan2 (y0, x0);
+ th_1 = atan2 (y1, x1);
+ if (radius > 0)
+ {
+ /* curve to the left */
+ if (th_0 < th_1) th_0 += M_PI * 2;
+ n_pts = ceil ((th_0 - th_1) / theta);
+ }
+ else
+ {
+ /* curve to the right */
+ if (th_1 < th_0) th_1 += M_PI * 2;
+ n_pts = ceil ((th_1 - th_0) / theta);
+ }
+#ifdef VERBOSE
+ printf ("start %f %f; th_0 = %f, th_1 = %f, r = %f, theta = %f\n", x0, y0, th_0, th_1, radius, theta);
+#endif
+ art_vpath_add_point (p_vpath, pn, pn_max,
+ ART_LINETO, xc + x0, yc + y0);
+ for (i = 1; i < n_pts; i++)
+ {
+ theta = th_0 + (th_1 - th_0) * i / n_pts;
+ art_vpath_add_point (p_vpath, pn, pn_max,
+ ART_LINETO, xc + cos (theta) * aradius,
+ yc + sin (theta) * aradius);
+#ifdef VERBOSE
+ printf ("mid %f %f\n", cos (theta) * radius, sin (theta) * radius);
+#endif
+ }
+ art_vpath_add_point (p_vpath, pn, pn_max,
+ ART_LINETO, xc + x1, yc + y1);
+#ifdef VERBOSE
+ printf ("end %f %f\n", x1, y1);
+#endif
+}
+
+/* Assume that forw and rev are at point i0. Bring them to i1,
+ joining with the vector i1 - i2.
+
+ This used to be true, but isn't now that the stroke_raw code is
+ filtering out (near)zero length vectors: {It so happens that all
+ invocations of this function maintain the precondition i1 = i0 + 1,
+ so we could decrease the number of arguments by one. We haven't
+ done that here, though.}
+
+ forw is to the line's right and rev is to its left.
+
+ Precondition: no zero-length vectors, otherwise a divide by
+ zero will happen. */
+static void
+render_seg (ArtVpath **p_forw, int *pn_forw, int *pn_forw_max,
+ ArtVpath **p_rev, int *pn_rev, int *pn_rev_max,
+ ArtVpath *vpath, int i0, int i1, int i2,
+ ArtPathStrokeJoinType join,
+ double line_width, double miter_limit, double flatness)
+{
+ double dx0, dy0;
+ double dx1, dy1;
+ double dlx0, dly0;
+ double dlx1, dly1;
+ double dmx, dmy;
+ double dmr2;
+ double scale;
+ double cross;
+
+#ifdef VERBOSE
+ printf ("join style = %d\n", join);
+#endif
+
+ /* The vectors of the lines from i0 to i1 and i1 to i2. */
+ dx0 = vpath[i1].x - vpath[i0].x;
+ dy0 = vpath[i1].y - vpath[i0].y;
+
+ dx1 = vpath[i2].x - vpath[i1].x;
+ dy1 = vpath[i2].y - vpath[i1].y;
+
+ /* Set dl[xy]0 to the vector from i0 to i1, rotated counterclockwise
+ 90 degrees, and scaled to the length of line_width. */
+ scale = line_width / sqrt (dx0 * dx0 + dy0 * dy0);
+ dlx0 = dy0 * scale;
+ dly0 = -dx0 * scale;
+
+ /* Set dl[xy]1 to the vector from i1 to i2, rotated counterclockwise
+ 90 degrees, and scaled to the length of line_width. */
+ scale = line_width / sqrt (dx1 * dx1 + dy1 * dy1);
+ dlx1 = dy1 * scale;
+ dly1 = -dx1 * scale;
+
+#ifdef VERBOSE
+ printf ("%% render_seg: (%g, %g) - (%g, %g) - (%g, %g)\n",
+ vpath[i0].x, vpath[i0].y,
+ vpath[i1].x, vpath[i1].y,
+ vpath[i2].x, vpath[i2].y);
+
+ printf ("%% render_seg: d[xy]0 = (%g, %g), dl[xy]0 = (%g, %g)\n",
+ dx0, dy0, dlx0, dly0);
+
+ printf ("%% render_seg: d[xy]1 = (%g, %g), dl[xy]1 = (%g, %g)\n",
+ dx1, dy1, dlx1, dly1);
+#endif
+
+ /* now, forw's last point is expected to be colinear along d[xy]0
+ to point i0 - dl[xy]0, and rev with i0 + dl[xy]0. */
+
+ /* positive for positive area (i.e. left turn) */
+ cross = dx1 * dy0 - dx0 * dy1;
+
+ dmx = (dlx0 + dlx1) * 0.5;
+ dmy = (dly0 + dly1) * 0.5;
+ dmr2 = dmx * dmx + dmy * dmy;
+
+ if (join == ART_PATH_STROKE_JOIN_MITER &&
+ dmr2 * miter_limit * miter_limit < line_width * line_width)
+ join = ART_PATH_STROKE_JOIN_BEVEL;
+
+ /* the case when dmr2 is zero or very small bothers me
+ (i.e. near a 180 degree angle)
+ ALEX: So, we avoid the optimization when dmr2 is very small. This should
+ be safe since dmx/y is only used in optimization and in MITER case, and MITER
+ should be converted to BEVEL when dmr2 is very small. */
+ if (dmr2 > EPSILON_2)
+ {
+ scale = line_width * line_width / dmr2;
+ dmx *= scale;
+ dmy *= scale;
+ }
+
+ if (cross * cross < EPSILON_2 && dx0 * dx1 + dy0 * dy1 >= 0)
+ {
+ /* going straight */
+#ifdef VERBOSE
+ printf ("%% render_seg: straight\n");
+#endif
+ art_vpath_add_point (p_forw, pn_forw, pn_forw_max,
+ ART_LINETO, vpath[i1].x - dlx0, vpath[i1].y - dly0);
+ art_vpath_add_point (p_rev, pn_rev, pn_rev_max,
+ ART_LINETO, vpath[i1].x + dlx0, vpath[i1].y + dly0);
+ }
+ else if (cross > 0)
+ {
+ /* left turn, forw is outside and rev is inside */
+
+#ifdef VERBOSE
+ printf ("%% render_seg: left\n");
+#endif
+ if (
+#ifdef NO_OPTIMIZE_INNER
+ 0 &&
+#endif
+ (dmr2 > EPSILON_2) &&
+ /* check that i1 + dm[xy] is inside i0-i1 rectangle */
+ (dx0 + dmx) * dx0 + (dy0 + dmy) * dy0 > 0 &&
+ /* and that i1 + dm[xy] is inside i1-i2 rectangle */
+ ((dx1 - dmx) * dx1 + (dy1 - dmy) * dy1 > 0)
+#ifdef PEDANTIC_INNER
+ &&
+ /* check that i1 + dl[xy]1 is inside i0-i1 rectangle */
+ (dx0 + dlx1) * dx0 + (dy0 + dly1) * dy0 > 0 &&
+ /* and that i1 + dl[xy]0 is inside i1-i2 rectangle */
+ ((dx1 - dlx0) * dx1 + (dy1 - dly0) * dy1 > 0)
+#endif
+ )
+ {
+ /* can safely add single intersection point */
+ art_vpath_add_point (p_rev, pn_rev, pn_rev_max,
+ ART_LINETO, vpath[i1].x + dmx, vpath[i1].y + dmy);
+ }
+ else
+ {
+ /* need to loop-de-loop the inside */
+ art_vpath_add_point (p_rev, pn_rev, pn_rev_max,
+ ART_LINETO, vpath[i1].x + dlx0, vpath[i1].y + dly0);
+ art_vpath_add_point (p_rev, pn_rev, pn_rev_max,
+ ART_LINETO, vpath[i1].x, vpath[i1].y);
+ art_vpath_add_point (p_rev, pn_rev, pn_rev_max,
+ ART_LINETO, vpath[i1].x + dlx1, vpath[i1].y + dly1);
+ }
+
+ if (join == ART_PATH_STROKE_JOIN_BEVEL)
+ {
+ /* bevel */
+ art_vpath_add_point (p_forw, pn_forw, pn_forw_max,
+ ART_LINETO, vpath[i1].x - dlx0, vpath[i1].y - dly0);
+ art_vpath_add_point (p_forw, pn_forw, pn_forw_max,
+ ART_LINETO, vpath[i1].x - dlx1, vpath[i1].y - dly1);
+ }
+ else if (join == ART_PATH_STROKE_JOIN_MITER)
+ {
+ art_vpath_add_point (p_forw, pn_forw, pn_forw_max,
+ ART_LINETO, vpath[i1].x - dmx, vpath[i1].y - dmy);
+ }
+ else if (join == ART_PATH_STROKE_JOIN_ROUND) {
+ art_svp_vpath_stroke_arc (p_forw, pn_forw, pn_forw_max,
+ vpath[i1].x, vpath[i1].y,
+ -dlx0, -dly0,
+ -dlx1, -dly1,
+ line_width,
+ flatness);
+ }
+ }
+ else
+ {
+ /* right turn, rev is outside and forw is inside */
+#ifdef VERBOSE
+ printf ("%% render_seg: right\n");
+#endif
+
+ if (
+#ifdef NO_OPTIMIZE_INNER
+ 0 &&
+#endif
+ (dmr2 > EPSILON_2) &&
+ /* check that i1 - dm[xy] is inside i0-i1 rectangle */
+ (dx0 - dmx) * dx0 + (dy0 - dmy) * dy0 > 0 &&
+ /* and that i1 - dm[xy] is inside i1-i2 rectangle */
+ ((dx1 + dmx) * dx1 + (dy1 + dmy) * dy1 > 0)
+#ifdef PEDANTIC_INNER
+ &&
+ /* check that i1 - dl[xy]1 is inside i0-i1 rectangle */
+ (dx0 - dlx1) * dx0 + (dy0 - dly1) * dy0 > 0 &&
+ /* and that i1 - dl[xy]0 is inside i1-i2 rectangle */
+ ((dx1 + dlx0) * dx1 + (dy1 + dly0) * dy1 > 0)
+#endif
+ )
+ {
+ /* can safely add single intersection point */
+ art_vpath_add_point (p_forw, pn_forw, pn_forw_max,
+ ART_LINETO, vpath[i1].x - dmx, vpath[i1].y - dmy);
+ }
+ else
+ {
+ /* need to loop-de-loop the inside */
+ art_vpath_add_point (p_forw, pn_forw, pn_forw_max,
+ ART_LINETO, vpath[i1].x - dlx0, vpath[i1].y - dly0);
+ art_vpath_add_point (p_forw, pn_forw, pn_forw_max,
+ ART_LINETO, vpath[i1].x, vpath[i1].y);
+ art_vpath_add_point (p_forw, pn_forw, pn_forw_max,
+ ART_LINETO, vpath[i1].x - dlx1, vpath[i1].y - dly1);
+ }
+
+ if (join == ART_PATH_STROKE_JOIN_BEVEL)
+ {
+ /* bevel */
+ art_vpath_add_point (p_rev, pn_rev, pn_rev_max,
+ ART_LINETO, vpath[i1].x + dlx0, vpath[i1].y + dly0);
+ art_vpath_add_point (p_rev, pn_rev, pn_rev_max,
+ ART_LINETO, vpath[i1].x + dlx1, vpath[i1].y + dly1);
+ }
+ else if (join == ART_PATH_STROKE_JOIN_MITER)
+ {
+ art_vpath_add_point (p_rev, pn_rev, pn_rev_max,
+ ART_LINETO, vpath[i1].x + dmx, vpath[i1].y + dmy);
+ }
+ else if (join == ART_PATH_STROKE_JOIN_ROUND) {
+ art_svp_vpath_stroke_arc (p_rev, pn_rev, pn_rev_max,
+ vpath[i1].x, vpath[i1].y,
+ dlx0, dly0,
+ dlx1, dly1,
+ -line_width,
+ flatness);
+ }
+
+ }
+}
+
+/* caps i1, under the assumption of a vector from i0 */
+static void
+render_cap (ArtVpath **p_result, int *pn_result, int *pn_result_max,
+ ArtVpath *vpath, int i0, int i1,
+ ArtPathStrokeCapType cap, double line_width, double flatness)
+{
+ double dx0, dy0;
+ double dlx0, dly0;
+ double scale;
+ int n_pts;
+ int i;
+
+ dx0 = vpath[i1].x - vpath[i0].x;
+ dy0 = vpath[i1].y - vpath[i0].y;
+
+ /* Set dl[xy]0 to the vector from i0 to i1, rotated counterclockwise
+ 90 degrees, and scaled to the length of line_width. */
+ scale = line_width / sqrt (dx0 * dx0 + dy0 * dy0);
+ dlx0 = dy0 * scale;
+ dly0 = -dx0 * scale;
+
+#ifdef VERBOSE
+ printf ("cap style = %d\n", cap);
+#endif
+
+ switch (cap)
+ {
+ case ART_PATH_STROKE_CAP_BUTT:
+ art_vpath_add_point (p_result, pn_result, pn_result_max,
+ ART_LINETO, vpath[i1].x - dlx0, vpath[i1].y - dly0);
+ art_vpath_add_point (p_result, pn_result, pn_result_max,
+ ART_LINETO, vpath[i1].x + dlx0, vpath[i1].y + dly0);
+ break;
+ case ART_PATH_STROKE_CAP_ROUND:
+ n_pts = ceil (M_PI / (2.0 * M_SQRT2 * sqrt (flatness / line_width)));
+ art_vpath_add_point (p_result, pn_result, pn_result_max,
+ ART_LINETO, vpath[i1].x - dlx0, vpath[i1].y - dly0);
+ for (i = 1; i < n_pts; i++)
+ {
+ double theta, c_th, s_th;
+
+ theta = M_PI * i / n_pts;
+ c_th = cos (theta);
+ s_th = sin (theta);
+ art_vpath_add_point (p_result, pn_result, pn_result_max,
+ ART_LINETO,
+ vpath[i1].x - dlx0 * c_th - dly0 * s_th,
+ vpath[i1].y - dly0 * c_th + dlx0 * s_th);
+ }
+ art_vpath_add_point (p_result, pn_result, pn_result_max,
+ ART_LINETO, vpath[i1].x + dlx0, vpath[i1].y + dly0);
+ break;
+ case ART_PATH_STROKE_CAP_SQUARE:
+ art_vpath_add_point (p_result, pn_result, pn_result_max,
+ ART_LINETO,
+ vpath[i1].x - dlx0 - dly0,
+ vpath[i1].y - dly0 + dlx0);
+ art_vpath_add_point (p_result, pn_result, pn_result_max,
+ ART_LINETO,
+ vpath[i1].x + dlx0 - dly0,
+ vpath[i1].y + dly0 + dlx0);
+ break;
+ }
+}
+
+/**
+ * art_svp_from_vpath_raw: Stroke a vector path, raw version
+ * @vpath: #ArtVPath to stroke.
+ * @join: Join style.
+ * @cap: Cap style.
+ * @line_width: Width of stroke.
+ * @miter_limit: Miter limit.
+ * @flatness: Flatness.
+ *
+ * Exactly the same as art_svp_vpath_stroke(), except that the resulting
+ * stroke outline may self-intersect and have regions of winding number
+ * greater than 1.
+ *
+ * Return value: Resulting raw stroked outline in svp format.
+ **/
+ArtVpath *
+art_svp_vpath_stroke_raw (ArtVpath *vpath,
+ ArtPathStrokeJoinType join,
+ ArtPathStrokeCapType cap,
+ double line_width,
+ double miter_limit,
+ double flatness)
+{
+ int begin_idx, end_idx;
+ int i;
+ ArtVpath *forw, *rev;
+ int n_forw, n_rev;
+ int n_forw_max, n_rev_max;
+ ArtVpath *result;
+ int n_result, n_result_max;
+ double half_lw = 0.5 * line_width;
+ int closed;
+ int last, xthis, next, second;
+ double dx, dy;
+
+ n_forw_max = 16;
+ forw = art_new (ArtVpath, n_forw_max);
+
+ n_rev_max = 16;
+ rev = art_new (ArtVpath, n_rev_max);
+
+ n_result = 0;
+ n_result_max = 16;
+ result = art_new (ArtVpath, n_result_max);
+
+ for (begin_idx = 0; vpath[begin_idx].code != ART_END; begin_idx = end_idx)
+ {
+ n_forw = 0;
+ n_rev = 0;
+
+ closed = (vpath[begin_idx].code == ART_MOVETO);
+
+ /* we don't know what the first point joins with until we get to the
+ last point and see if it's closed. So we start with the second
+ line in the path.
+
+ Note: this is not strictly true (we now know it's closed from
+ the opening pathcode), but why fix code that isn't broken?
+ */
+
+ xthis = begin_idx;
+ /* skip over identical points at the beginning of the subpath */
+ for (i = xthis + 1; vpath[i].code == ART_LINETO; i++)
+ {
+ dx = vpath[i].x - vpath[xthis].x;
+ dy = vpath[i].y - vpath[xthis].y;
+ if (dx * dx + dy * dy > EPSILON_2)
+ break;
+ }
+ next = i;
+ second = next;
+
+ /* invariant: this doesn't coincide with next */
+ while (vpath[next].code == ART_LINETO)
+ {
+ last = xthis;
+ xthis = next;
+ /* skip over identical points after the beginning of the subpath */
+ for (i = xthis + 1; vpath[i].code == ART_LINETO; i++)
+ {
+ dx = vpath[i].x - vpath[xthis].x;
+ dy = vpath[i].y - vpath[xthis].y;
+ if (dx * dx + dy * dy > EPSILON_2)
+ break;
+ }
+ next = i;
+ if (vpath[next].code != ART_LINETO)
+ {
+ /* reached end of path */
+ /* make "closed" detection conform to PostScript
+ semantics (i.e. explicit closepath code rather than
+ just the fact that end of the path is the beginning) */
+ if (closed &&
+ vpath[xthis].x == vpath[begin_idx].x &&
+ vpath[xthis].y == vpath[begin_idx].y)
+ {
+ int j;
+
+ /* path is closed, render join to beginning */
+ render_seg (&forw, &n_forw, &n_forw_max,
+ &rev, &n_rev, &n_rev_max,
+ vpath, last, xthis, second,
+ join, half_lw, miter_limit, flatness);
+
+#ifdef VERBOSE
+ printf ("%% forw %d, rev %d\n", n_forw, n_rev);
+#endif
+ /* do forward path */
+ art_vpath_add_point (&result, &n_result, &n_result_max,
+ ART_MOVETO, forw[n_forw - 1].x,
+ forw[n_forw - 1].y);
+ for (j = 0; j < n_forw; j++)
+ art_vpath_add_point (&result, &n_result, &n_result_max,
+ ART_LINETO, forw[j].x,
+ forw[j].y);
+
+ /* do reverse path, reversed */
+ art_vpath_add_point (&result, &n_result, &n_result_max,
+ ART_MOVETO, rev[0].x,
+ rev[0].y);
+ for (j = n_rev - 1; j >= 0; j--)
+ art_vpath_add_point (&result, &n_result, &n_result_max,
+ ART_LINETO, rev[j].x,
+ rev[j].y);
+ }
+ else
+ {
+ /* path is open */
+ int j;
+
+ /* add to forw rather than result to ensure that
+ forw has at least one point. */
+ render_cap (&forw, &n_forw, &n_forw_max,
+ vpath, last, xthis,
+ cap, half_lw, flatness);
+ art_vpath_add_point (&result, &n_result, &n_result_max,
+ ART_MOVETO, forw[0].x,
+ forw[0].y);
+ for (j = 1; j < n_forw; j++)
+ art_vpath_add_point (&result, &n_result, &n_result_max,
+ ART_LINETO, forw[j].x,
+ forw[j].y);
+ for (j = n_rev - 1; j >= 0; j--)
+ art_vpath_add_point (&result, &n_result, &n_result_max,
+ ART_LINETO, rev[j].x,
+ rev[j].y);
+ render_cap (&result, &n_result, &n_result_max,
+ vpath, second, begin_idx,
+ cap, half_lw, flatness);
+ art_vpath_add_point (&result, &n_result, &n_result_max,
+ ART_LINETO, forw[0].x,
+ forw[0].y);
+ }
+ }
+ else
+ render_seg (&forw, &n_forw, &n_forw_max,
+ &rev, &n_rev, &n_rev_max,
+ vpath, last, xthis, next,
+ join, half_lw, miter_limit, flatness);
+ }
+ end_idx = next;
+ }
+
+ art_free (forw);
+ art_free (rev);
+#ifdef VERBOSE
+ printf ("%% n_result = %d\n", n_result);
+#endif
+ art_vpath_add_point (&result, &n_result, &n_result_max, ART_END, 0, 0);
+ return result;
+}
+
+#define noVERBOSE
+
+#ifdef VERBOSE
+
+#define XOFF 50
+#define YOFF 700
+
+static void
+print_ps_vpath (ArtVpath *vpath)
+{
+ int i;
+
+ for (i = 0; vpath[i].code != ART_END; i++)
+ {
+ switch (vpath[i].code)
+ {
+ case ART_MOVETO:
+ printf ("%g %g moveto\n", XOFF + vpath[i].x, YOFF - vpath[i].y);
+ break;
+ case ART_LINETO:
+ printf ("%g %g lineto\n", XOFF + vpath[i].x, YOFF - vpath[i].y);
+ break;
+ default:
+ break;
+ }
+ }
+ printf ("stroke showpage\n");
+}
+
+static void
+print_ps_svp (ArtSVP *vpath)
+{
+ int i, j;
+
+ printf ("%% begin\n");
+ for (i = 0; i < vpath->n_segs; i++)
+ {
+ printf ("%g setgray\n", vpath->segs[i].dir ? 0.7 : 0);
+ for (j = 0; j < vpath->segs[i].n_points; j++)
+ {
+ printf ("%g %g %s\n",
+ XOFF + vpath->segs[i].points[j].x,
+ YOFF - vpath->segs[i].points[j].y,
+ j ? "lineto" : "moveto");
+ }
+ printf ("stroke\n");
+ }
+
+ printf ("showpage\n");
+}
+#endif
+
+/* Render a vector path into a stroked outline.
+
+ Status of this routine:
+
+ Basic correctness: Only miter and bevel line joins are implemented,
+ and only butt line caps. Otherwise, seems to be fine.
+
+ Numerical stability: We cheat (adding random perturbation). Thus,
+ it seems very likely that no numerical stability problems will be
+ seen in practice.
+
+ Speed: Should be pretty good.
+
+ Precision: The perturbation fuzzes the coordinates slightly,
+ but not enough to be visible. */
+/**
+ * art_svp_vpath_stroke: Stroke a vector path.
+ * @vpath: #ArtVPath to stroke.
+ * @join: Join style.
+ * @cap: Cap style.
+ * @line_width: Width of stroke.
+ * @miter_limit: Miter limit.
+ * @flatness: Flatness.
+ *
+ * Computes an svp representing the stroked outline of @vpath. The
+ * width of the stroked line is @line_width.
+ *
+ * Lines are joined according to the @join rule. Possible values are
+ * ART_PATH_STROKE_JOIN_MITER (for mitered joins),
+ * ART_PATH_STROKE_JOIN_ROUND (for round joins), and
+ * ART_PATH_STROKE_JOIN_BEVEL (for bevelled joins). The mitered join
+ * is converted to a bevelled join if the miter would extend to a
+ * distance of more than @miter_limit * @line_width from the actual
+ * join point.
+ *
+ * If there are open subpaths, the ends of these subpaths are capped
+ * according to the @cap rule. Possible values are
+ * ART_PATH_STROKE_CAP_BUTT (squared cap, extends exactly to end
+ * point), ART_PATH_STROKE_CAP_ROUND (rounded half-circle centered at
+ * the end point), and ART_PATH_STROKE_CAP_SQUARE (squared cap,
+ * extending half @line_width past the end point).
+ *
+ * The @flatness parameter controls the accuracy of the rendering. It
+ * is most important for determining the number of points to use to
+ * approximate circular arcs for round lines and joins. In general, the
+ * resulting vector path will be within @flatness pixels of the "ideal"
+ * path containing actual circular arcs. I reserve the right to use
+ * the @flatness parameter to convert bevelled joins to miters for very
+ * small turn angles, as this would reduce the number of points in the
+ * resulting outline path.
+ *
+ * The resulting path is "clean" with respect to self-intersections, i.e.
+ * the winding number is 0 or 1 at each point.
+ *
+ * Return value: Resulting stroked outline in svp format.
+ **/
+ArtSVP *
+art_svp_vpath_stroke (ArtVpath *vpath,
+ ArtPathStrokeJoinType join,
+ ArtPathStrokeCapType cap,
+ double line_width,
+ double miter_limit,
+ double flatness)
+{
+#ifdef ART_USE_NEW_INTERSECTOR
+ ArtVpath *vpath_stroke;
+ ArtSVP *svp, *svp2;
+ ArtSvpWriter *swr;
+
+ vpath_stroke = art_svp_vpath_stroke_raw (vpath, join, cap,
+ line_width, miter_limit, flatness);
+#ifdef VERBOSE
+ //print_ps_vpath (vpath_stroke);
+#endif
+ svp = art_svp_from_vpath (vpath_stroke);
+#ifdef VERBOSE
+ //print_ps_svp (svp);
+#endif
+ art_free (vpath_stroke);
+
+ swr = art_svp_writer_rewind_new (ART_WIND_RULE_NONZERO);
+ art_svp_intersector (svp, swr);
+
+ svp2 = art_svp_writer_rewind_reap (swr);
+#ifdef VERBOSE
+ //print_ps_svp (svp2);
+#endif
+ art_svp_free (svp);
+ return svp2;
+#else
+ ArtVpath *vpath_stroke, *vpath2;
+ ArtSVP *svp, *svp2, *svp3;
+
+ vpath_stroke = art_svp_vpath_stroke_raw (vpath, join, cap,
+ line_width, miter_limit, flatness);
+#ifdef VERBOSE
+ //print_ps_vpath (vpath_stroke);
+#endif
+ vpath2 = art_vpath_perturb (vpath_stroke);
+#ifdef VERBOSE
+ //print_ps_vpath (vpath2);
+#endif
+ art_free (vpath_stroke);
+ svp = art_svp_from_vpath (vpath2);
+#ifdef VERBOSE
+ //print_ps_svp (svp);
+#endif
+ art_free (vpath2);
+ svp2 = art_svp_uncross (svp);
+#ifdef VERBOSE
+ //print_ps_svp (svp2);
+#endif
+ art_svp_free (svp);
+ svp3 = art_svp_rewind_uncrossed (svp2, ART_WIND_RULE_NONZERO);
+#ifdef VERBOSE
+ //print_ps_svp (svp3);
+#endif
+ art_svp_free (svp2);
+
+ return svp3;
+#endif
+}
diff -Nru swftools-0.9.2+ds1/lib/art/art_svp_vpath_stroke.h swftools-0.9.1/lib/art/art_svp_vpath_stroke.h
--- swftools-0.9.2+ds1/lib/art/art_svp_vpath_stroke.h 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/art/art_svp_vpath_stroke.h 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,70 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __ART_SVP_VPATH_STROKE_H__
+#define __ART_SVP_VPATH_STROKE_H__
+
+/* Sort vector paths into sorted vector paths. */
+
+#ifdef LIBART_COMPILATION
+#include "art_svp.h"
+#include "art_vpath.h"
+#else
+#include "art_svp.h"
+#include "art_vpath.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+typedef enum {
+ ART_PATH_STROKE_JOIN_MITER,
+ ART_PATH_STROKE_JOIN_ROUND,
+ ART_PATH_STROKE_JOIN_BEVEL
+} ArtPathStrokeJoinType;
+
+typedef enum {
+ ART_PATH_STROKE_CAP_BUTT,
+ ART_PATH_STROKE_CAP_ROUND,
+ ART_PATH_STROKE_CAP_SQUARE
+} ArtPathStrokeCapType;
+
+ArtSVP *
+art_svp_vpath_stroke (ArtVpath *vpath,
+ ArtPathStrokeJoinType join,
+ ArtPathStrokeCapType cap,
+ double line_width,
+ double miter_limit,
+ double flatness);
+
+/* This version may have winding numbers exceeding 1. */
+ArtVpath *
+art_svp_vpath_stroke_raw (ArtVpath *vpath,
+ ArtPathStrokeJoinType join,
+ ArtPathStrokeCapType cap,
+ double line_width,
+ double miter_limit,
+ double flatness);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __ART_SVP_VPATH_STROKE_H__ */
diff -Nru swftools-0.9.2+ds1/lib/art/art_svp_wind.c swftools-0.9.1/lib/art/art_svp_wind.c
--- swftools-0.9.2+ds1/lib/art/art_svp_wind.c 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/art/art_svp_wind.c 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,1545 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998-2000 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/* Primitive intersection and winding number operations on sorted
+ vector paths.
+
+ These routines are internal to libart, used to construct operations
+ like intersection, union, and difference. */
+
+#include "config.h"
+#include "art_svp_wind.h"
+
+#include /* for printf of debugging info */
+#include /* for memcpy */
+#include
+#include "art_misc.h"
+
+#include "art_rect.h"
+#include "art_svp.h"
+
+#define noVERBOSE
+
+#define PT_EQ(p1,p2) ((p1).x == (p2).x && (p1).y == (p2).y)
+
+#define PT_CLOSE(p1,p2) (fabs ((p1).x - (p2).x) < 1e-6 && fabs ((p1).y - (p2).y) < 1e-6)
+
+/* return nonzero and set *p to the intersection point if the lines
+ z0-z1 and z2-z3 intersect each other. */
+static int
+intersect_lines (ArtPoint z0, ArtPoint z1, ArtPoint z2, ArtPoint z3,
+ ArtPoint *p)
+{
+ double a01, b01, c01;
+ double a23, b23, c23;
+ double d0, d1, d2, d3;
+ double det;
+
+ /* if the vectors share an endpoint, they don't intersect */
+ if (PT_EQ (z0, z2) || PT_EQ (z0, z3) || PT_EQ (z1, z2) || PT_EQ (z1, z3))
+ return 0;
+
+#if 0
+ if (PT_CLOSE (z0, z2) || PT_CLOSE (z0, z3) || PT_CLOSE (z1, z2) || PT_CLOSE (z1, z3))
+ return 0;
+#endif
+
+ /* find line equations ax + by + c = 0 */
+ a01 = z0.y - z1.y;
+ b01 = z1.x - z0.x;
+ c01 = -(z0.x * a01 + z0.y * b01);
+ /* = -((z0.y - z1.y) * z0.x + (z1.x - z0.x) * z0.y)
+ = (z1.x * z0.y - z1.y * z0.x) */
+
+ d2 = a01 * z2.x + b01 * z2.y + c01;
+ d3 = a01 * z3.x + b01 * z3.y + c01;
+ if ((d2 > 0) == (d3 > 0))
+ return 0;
+
+ a23 = z2.y - z3.y;
+ b23 = z3.x - z2.x;
+ c23 = -(z2.x * a23 + z2.y * b23);
+
+ d0 = a23 * z0.x + b23 * z0.y + c23;
+ d1 = a23 * z1.x + b23 * z1.y + c23;
+ if ((d0 > 0) == (d1 > 0))
+ return 0;
+
+ /* now we definitely know that the lines intersect */
+ /* solve the two linear equations ax + by + c = 0 */
+ det = 1.0 / (a01 * b23 - a23 * b01);
+ p->x = det * (c23 * b01 - c01 * b23);
+ p->y = det * (c01 * a23 - c23 * a01);
+
+ return 1;
+}
+
+#define EPSILON 1e-6
+
+static double
+trap_epsilon (double v)
+{
+ const double epsilon = EPSILON;
+
+ if (v < epsilon && v > -epsilon) return 0;
+ else return v;
+}
+
+/* Determine the order of line segments z0-z1 and z2-z3.
+ Return +1 if z2-z3 lies entirely to the right of z0-z1,
+ -1 if entirely to the left,
+ or 0 if overlap.
+
+ The case analysis in this function is quite ugly. The fact that it's
+ almost 200 lines long is ridiculous.
+
+ Ok, so here's the plan to cut it down:
+
+ First, do a bounding line comparison on the x coordinates. This is pretty
+ much the common case, and should go quickly. It also takes care of the
+ case where both lines are horizontal.
+
+ Then, do d0 and d1 computation, but only if a23 is nonzero.
+
+ Finally, do d2 and d3 computation, but only if a01 is nonzero.
+
+ Fall through to returning 0 (this will happen when both lines are
+ horizontal and they overlap).
+ */
+static int
+x_order (ArtPoint z0, ArtPoint z1, ArtPoint z2, ArtPoint z3)
+{
+ double a01, b01, c01;
+ double a23, b23, c23;
+ double d0, d1, d2, d3;
+
+ if (z0.y == z1.y)
+ {
+ if (z2.y == z3.y)
+ {
+ double x01min, x01max;
+ double x23min, x23max;
+
+ if (z0.x > z1.x)
+ {
+ x01min = z1.x;
+ x01max = z0.x;
+ }
+ else
+ {
+ x01min = z0.x;
+ x01max = z1.x;
+ }
+
+ if (z2.x > z3.x)
+ {
+ x23min = z3.x;
+ x23max = z2.x;
+ }
+ else
+ {
+ x23min = z2.x;
+ x23max = z3.x;
+ }
+
+ if (x23min >= x01max) return 1;
+ else if (x01min >= x23max) return -1;
+ else return 0;
+ }
+ else
+ {
+ /* z0-z1 is horizontal, z2-z3 isn't */
+ a23 = z2.y - z3.y;
+ b23 = z3.x - z2.x;
+ c23 = -(z2.x * a23 + z2.y * b23);
+
+ if (z3.y < z2.y)
+ {
+ a23 = -a23;
+ b23 = -b23;
+ c23 = -c23;
+ }
+
+ d0 = trap_epsilon (a23 * z0.x + b23 * z0.y + c23);
+ d1 = trap_epsilon (a23 * z1.x + b23 * z1.y + c23);
+
+ if (d0 > 0)
+ {
+ if (d1 >= 0) return 1;
+ else return 0;
+ }
+ else if (d0 == 0)
+ {
+ if (d1 > 0) return 1;
+ else if (d1 < 0) return -1;
+ else /*printf ("case 1 degenerate\n")*/;
+ return 0;
+ }
+ else /* d0 < 0 */
+ {
+ if (d1 <= 0) return -1;
+ else return 0;
+ }
+ }
+ }
+ else if (z2.y == z3.y)
+ {
+ /* z2-z3 is horizontal, z0-z1 isn't */
+ a01 = z0.y - z1.y;
+ b01 = z1.x - z0.x;
+ c01 = -(z0.x * a01 + z0.y * b01);
+ /* = -((z0.y - z1.y) * z0.x + (z1.x - z0.x) * z0.y)
+ = (z1.x * z0.y - z1.y * z0.x) */
+
+ if (z1.y < z0.y)
+ {
+ a01 = -a01;
+ b01 = -b01;
+ c01 = -c01;
+ }
+
+ d2 = trap_epsilon (a01 * z2.x + b01 * z2.y + c01);
+ d3 = trap_epsilon (a01 * z3.x + b01 * z3.y + c01);
+
+ if (d2 > 0)
+ {
+ if (d3 >= 0) return -1;
+ else return 0;
+ }
+ else if (d2 == 0)
+ {
+ if (d3 > 0) return -1;
+ else if (d3 < 0) return 1;
+ else printf ("case 2 degenerate\n");
+ return 0;
+ }
+ else /* d2 < 0 */
+ {
+ if (d3 <= 0) return 1;
+ else return 0;
+ }
+ }
+
+ /* find line equations ax + by + c = 0 */
+ a01 = z0.y - z1.y;
+ b01 = z1.x - z0.x;
+ c01 = -(z0.x * a01 + z0.y * b01);
+ /* = -((z0.y - z1.y) * z0.x + (z1.x - z0.x) * z0.y)
+ = -(z1.x * z0.y - z1.y * z0.x) */
+
+ if (a01 > 0)
+ {
+ a01 = -a01;
+ b01 = -b01;
+ c01 = -c01;
+ }
+ /* so now, (a01, b01) points to the left, thus a01 * x + b01 * y + c01
+ is negative if the point lies to the right of the line */
+
+ d2 = trap_epsilon (a01 * z2.x + b01 * z2.y + c01);
+ d3 = trap_epsilon (a01 * z3.x + b01 * z3.y + c01);
+ if (d2 > 0)
+ {
+ if (d3 >= 0) return -1;
+ }
+ else if (d2 == 0)
+ {
+ if (d3 > 0) return -1;
+ else if (d3 < 0) return 1;
+ else
+ /*fprintf (stderr, "colinear!\n")*/;
+ }
+ else /* d2 < 0 */
+ {
+ if (d3 <= 0) return 1;
+ }
+
+ a23 = z2.y - z3.y;
+ b23 = z3.x - z2.x;
+ c23 = -(z2.x * a23 + z2.y * b23);
+
+ if (a23 > 0)
+ {
+ a23 = -a23;
+ b23 = -b23;
+ c23 = -c23;
+ }
+ d0 = trap_epsilon (a23 * z0.x + b23 * z0.y + c23);
+ d1 = trap_epsilon (a23 * z1.x + b23 * z1.y + c23);
+ if (d0 > 0)
+ {
+ if (d1 >= 0) return 1;
+ }
+ else if (d0 == 0)
+ {
+ if (d1 > 0) return 1;
+ else if (d1 < 0) return -1;
+ else
+ /*fprintf (stderr, "colinear!\n")*/;
+ }
+ else /* d0 < 0 */
+ {
+ if (d1 <= 0) return -1;
+ }
+
+ return 0;
+}
+
+/* similar to x_order, but to determine whether point z0 + epsilon lies to
+ the left of the line z2-z3 or to the right */
+static int
+x_order_2 (ArtPoint z0, ArtPoint z1, ArtPoint z2, ArtPoint z3)
+{
+ double a23, b23, c23;
+ double d0, d1;
+
+ a23 = z2.y - z3.y;
+ b23 = z3.x - z2.x;
+ c23 = -(z2.x * a23 + z2.y * b23);
+
+ if (a23 > 0)
+ {
+ a23 = -a23;
+ b23 = -b23;
+ c23 = -c23;
+ }
+
+ d0 = a23 * z0.x + b23 * z0.y + c23;
+
+ if (d0 > EPSILON)
+ return -1;
+ else if (d0 < -EPSILON)
+ return 1;
+
+ d1 = a23 * z1.x + b23 * z1.y + c23;
+ if (d1 > EPSILON)
+ return -1;
+ else if (d1 < -EPSILON)
+ return 1;
+
+ if (z0.x == z1.x && z1.x == z2.x && z2.x == z3.x)
+ {
+ //art_dprint ("x_order_2: colinear and horizontally aligned!\n");
+ return 0;
+ }
+
+ if (z0.x <= z2.x && z1.x <= z2.x && z0.x <= z3.x && z1.x <= z3.x)
+ return -1;
+ if (z0.x >= z2.x && z1.x >= z2.x && z0.x >= z3.x && z1.x >= z3.x)
+ return 1;
+
+ //fprintf (stderr, "x_order_2: colinear!\n");
+ return 0;
+}
+
+#ifdef DEAD_CODE
+/* Traverse the vector path, keeping it in x-sorted order.
+
+ This routine doesn't actually do anything - it's just here for
+ explanatory purposes. */
+void
+traverse (ArtSVP *vp)
+{
+ int *active_segs;
+ int n_active_segs;
+ int *cursor;
+ int seg_idx;
+ double y;
+ int tmp1, tmp2;
+ int asi;
+ int i, j;
+
+ active_segs = art_new (int, vp->n_segs);
+ cursor = art_new (int, vp->n_segs);
+
+ n_active_segs = 0;
+ seg_idx = 0;
+ y = vp->segs[0].points[0].y;
+ while (seg_idx < vp->n_segs || n_active_segs > 0)
+ {
+ printf ("y = %g\n", y);
+ /* delete segments ending at y from active list */
+ for (i = 0; i < n_active_segs; i++)
+ {
+ asi = active_segs[i];
+ if (vp->segs[asi].n_points - 1 == cursor[asi] &&
+ vp->segs[asi].points[cursor[asi]].y == y)
+ {
+ printf ("deleting %d\n", asi);
+ n_active_segs--;
+ for (j = i; j < n_active_segs; j++)
+ active_segs[j] = active_segs[j + 1];
+ i--;
+ }
+ }
+
+ /* insert new segments into the active list */
+ while (seg_idx < vp->n_segs && y == vp->segs[seg_idx].points[0].y)
+ {
+ cursor[seg_idx] = 0;
+ printf ("inserting %d\n", seg_idx);
+ for (i = 0; i < n_active_segs; i++)
+ {
+ asi = active_segs[i];
+ if (x_order (vp->segs[asi].points[cursor[asi]],
+ vp->segs[asi].points[cursor[asi] + 1],
+ vp->segs[seg_idx].points[0],
+ vp->segs[seg_idx].points[1]) == -1)
+ break;
+ }
+ tmp1 = seg_idx;
+ for (j = i; j < n_active_segs; j++)
+ {
+ tmp2 = active_segs[j];
+ active_segs[j] = tmp1;
+ tmp1 = tmp2;
+ }
+ active_segs[n_active_segs] = tmp1;
+ n_active_segs++;
+ seg_idx++;
+ }
+
+ /* all active segs cross the y scanline (considering segs to be
+ closed on top and open on bottom) */
+ for (i = 0; i < n_active_segs; i++)
+ {
+ asi = active_segs[i];
+ printf ("%d (%g, %g) - (%g, %g) %s\n", asi,
+ vp->segs[asi].points[cursor[asi]].x,
+ vp->segs[asi].points[cursor[asi]].y,
+ vp->segs[asi].points[cursor[asi] + 1].x,
+ vp->segs[asi].points[cursor[asi] + 1].y,
+ vp->segs[asi].dir ? "v" : "^");
+ }
+
+ /* advance y to the next event */
+ if (n_active_segs == 0)
+ {
+ if (seg_idx < vp->n_segs)
+ y = vp->segs[seg_idx].points[0].y;
+ /* else we're done */
+ }
+ else
+ {
+ asi = active_segs[0];
+ y = vp->segs[asi].points[cursor[asi] + 1].y;
+ for (i = 1; i < n_active_segs; i++)
+ {
+ asi = active_segs[i];
+ if (y > vp->segs[asi].points[cursor[asi] + 1].y)
+ y = vp->segs[asi].points[cursor[asi] + 1].y;
+ }
+ if (seg_idx < vp->n_segs && y > vp->segs[seg_idx].points[0].y)
+ y = vp->segs[seg_idx].points[0].y;
+ }
+
+ /* advance cursors to reach new y */
+ for (i = 0; i < n_active_segs; i++)
+ {
+ asi = active_segs[i];
+ while (cursor[asi] < vp->segs[asi].n_points - 1 &&
+ y >= vp->segs[asi].points[cursor[asi] + 1].y)
+ cursor[asi]++;
+ }
+ printf ("\n");
+ }
+ art_free (cursor);
+ art_free (active_segs);
+}
+#endif
+
+/* I believe that the loop will always break with i=1.
+
+ I think I'll want to change this from a simple sorted list to a
+ modified stack. ips[*][0] will get its own data structure, and
+ ips[*] will in general only be allocated if there is an intersection.
+ Finally, the segment can be traced through the initial point
+ (formerly ips[*][0]), backwards through the stack, and finally
+ to cursor + 1.
+
+ This change should cut down on allocation bandwidth, and also
+ eliminate the iteration through n_ipl below.
+
+*/
+static void
+insert_ip (int seg_i, int *n_ips, int *n_ips_max, ArtPoint **ips, ArtPoint ip)
+{
+ int i;
+ ArtPoint tmp1, tmp2;
+ int n_ipl;
+ ArtPoint *ipl;
+
+ n_ipl = n_ips[seg_i]++;
+ if (n_ipl == n_ips_max[seg_i])
+ art_expand (ips[seg_i], ArtPoint, n_ips_max[seg_i]);
+ ipl = ips[seg_i];
+ for (i = 1; i < n_ipl; i++)
+ if (ipl[i].y > ip.y)
+ break;
+ tmp1 = ip;
+ for (; i <= n_ipl; i++)
+ {
+ tmp2 = ipl[i];
+ ipl[i] = tmp1;
+ tmp1 = tmp2;
+ }
+}
+
+/* test active segment (i - 1) against i for intersection, if
+ so, add intersection point to both ips lists. */
+static void
+intersect_neighbors (int i, int *active_segs,
+ int *n_ips, int *n_ips_max, ArtPoint **ips,
+ int *cursor, ArtSVP *vp)
+{
+ ArtPoint z0, z1, z2, z3;
+ int asi01, asi23;
+ ArtPoint ip;
+
+ asi01 = active_segs[i - 1];
+
+ z0 = ips[asi01][0];
+ if (n_ips[asi01] == 1)
+ z1 = vp->segs[asi01].points[cursor[asi01] + 1];
+ else
+ z1 = ips[asi01][1];
+
+ asi23 = active_segs[i];
+
+ z2 = ips[asi23][0];
+ if (n_ips[asi23] == 1)
+ z3 = vp->segs[asi23].points[cursor[asi23] + 1];
+ else
+ z3 = ips[asi23][1];
+
+ if (intersect_lines (z0, z1, z2, z3, &ip))
+ {
+#ifdef VERBOSE
+ printf ("new intersection point: (%g, %g)\n", ip.x, ip.y);
+#endif
+ insert_ip (asi01, n_ips, n_ips_max, ips, ip);
+ insert_ip (asi23, n_ips, n_ips_max, ips, ip);
+ }
+}
+
+/* Add a new point to a segment in the svp.
+
+ Here, we also check to make sure that the segments satisfy nocross.
+ However, this is only valuable for debugging, and could possibly be
+ removed.
+*/
+static void
+svp_add_point (ArtSVP *svp, int *n_points_max,
+ ArtPoint p, int *seg_map, int *active_segs, int n_active_segs,
+ int i)
+{
+ int asi, asi_left, asi_right;
+ int n_points, n_points_left, n_points_right;
+ ArtSVPSeg *seg;
+
+ asi = seg_map[active_segs[i]];
+ seg = &svp->segs[asi];
+ n_points = seg->n_points;
+ /* find out whether neighboring segments share a point */
+ if (i > 0)
+ {
+ asi_left = seg_map[active_segs[i - 1]];
+ n_points_left = svp->segs[asi_left].n_points;
+ if (n_points_left > 1 &&
+ PT_EQ (svp->segs[asi_left].points[n_points_left - 2],
+ svp->segs[asi].points[n_points - 1]))
+ {
+ /* ok, new vector shares a top point with segment to the left -
+ now, check that it satisfies ordering invariant */
+ if (x_order (svp->segs[asi_left].points[n_points_left - 2],
+ svp->segs[asi_left].points[n_points_left - 1],
+ svp->segs[asi].points[n_points - 1],
+ p) < 1)
+
+ {
+#ifdef VERBOSE
+ printf ("svp_add_point: cross on left!\n");
+#endif
+ }
+ }
+ }
+
+ if (i + 1 < n_active_segs)
+ {
+ asi_right = seg_map[active_segs[i + 1]];
+ n_points_right = svp->segs[asi_right].n_points;
+ if (n_points_right > 1 &&
+ PT_EQ (svp->segs[asi_right].points[n_points_right - 2],
+ svp->segs[asi].points[n_points - 1]))
+ {
+ /* ok, new vector shares a top point with segment to the right -
+ now, check that it satisfies ordering invariant */
+ if (x_order (svp->segs[asi_right].points[n_points_right - 2],
+ svp->segs[asi_right].points[n_points_right - 1],
+ svp->segs[asi].points[n_points - 1],
+ p) > -1)
+ {
+#ifdef VERBOSE
+ printf ("svp_add_point: cross on right!\n");
+#endif
+ }
+ }
+ }
+ if (n_points_max[asi] == n_points)
+ art_expand (seg->points, ArtPoint, n_points_max[asi]);
+ seg->points[n_points] = p;
+ if (p.x < seg->bbox.x0)
+ seg->bbox.x0 = p.x;
+ else if (p.x > seg->bbox.x1)
+ seg->bbox.x1 = p.x;
+ seg->bbox.y1 = p.y;
+ seg->n_points++;
+}
+
+#if 0
+/* find where the segment (currently at i) is supposed to go, and return
+ the target index - if equal to i, then there is no crossing problem.
+
+ "Where it is supposed to go" is defined as following:
+
+ Delete element i, re-insert at position target (bumping everything
+ target and greater to the right).
+ */
+static int
+find_crossing (int i, int *active_segs, int n_active_segs,
+ int *cursor, ArtPoint **ips, int *n_ips, ArtSVP *vp)
+{
+ int asi, asi_left, asi_right;
+ ArtPoint p0, p1;
+ ArtPoint p0l, p1l;
+ ArtPoint p0r, p1r;
+ int target;
+
+ asi = active_segs[i];
+ p0 = ips[asi][0];
+ if (n_ips[asi] == 1)
+ p1 = vp->segs[asi].points[cursor[asi] + 1];
+ else
+ p1 = ips[asi][1];
+
+ for (target = i; target > 0; target--)
+ {
+ asi_left = active_segs[target - 1];
+ p0l = ips[asi_left][0];
+ if (n_ips[asi_left] == 1)
+ p1l = vp->segs[asi_left].points[cursor[asi_left] + 1];
+ else
+ p1l = ips[asi_left][1];
+ if (!PT_EQ (p0, p0l))
+ break;
+
+#ifdef VERBOSE
+ printf ("point matches on left (%g, %g) - (%g, %g) x (%g, %g) - (%g, %g)!\n",
+ p0l.x, p0l.y, p1l.x, p1l.y, p0.x, p0.y, p1.x, p1.y);
+#endif
+ if (x_order (p0l, p1l, p0, p1) == 1)
+ break;
+
+#ifdef VERBOSE
+ printf ("scanning to the left (i=%d, target=%d)\n", i, target);
+#endif
+ }
+
+ if (target < i) return target;
+
+ for (; target < n_active_segs - 1; target++)
+ {
+ asi_right = active_segs[target + 1];
+ p0r = ips[asi_right][0];
+ if (n_ips[asi_right] == 1)
+ p1r = vp->segs[asi_right].points[cursor[asi_right] + 1];
+ else
+ p1r = ips[asi_right][1];
+ if (!PT_EQ (p0, p0r))
+ break;
+
+#ifdef VERBOSE
+ printf ("point matches on left (%g, %g) - (%g, %g) x (%g, %g) - (%g, %g)!\n",
+ p0.x, p0.y, p1.x, p1.y, p0r.x, p0r.y, p1r.x, p1r.y);
+#endif
+ if (x_order (p0r, p1r, p0, p1) == 1)
+ break;
+
+#ifdef VERBOSE
+ printf ("scanning to the right (i=%d, target=%d)\n", i, target);
+#endif
+ }
+
+ return target;
+}
+#endif
+
+/* This routine handles the case where the segment changes its position
+ in the active segment list. Generally, this will happen when the
+ segment (defined by i and cursor) shares a top point with a neighbor,
+ but breaks the ordering invariant.
+
+ Essentially, this routine sorts the lines [start..end), all of which
+ share a top point. This is implemented as your basic insertion sort.
+
+ This routine takes care of intersecting the appropriate neighbors,
+ as well.
+
+ A first argument of -1 immediately returns, which helps reduce special
+ casing in the main unwind routine.
+*/
+static void
+fix_crossing (int start, int end, int *active_segs, int n_active_segs,
+ int *cursor, ArtPoint **ips, int *n_ips, int *n_ips_max,
+ ArtSVP *vp, int *seg_map,
+ ArtSVP **p_new_vp, int *pn_segs_max,
+ int **pn_points_max)
+{
+ int i, j;
+ int target;
+ int asi, asj;
+ ArtPoint p0i, p1i;
+ ArtPoint p0j, p1j;
+ int swap = 0;
+#ifdef VERBOSE
+ int k;
+#endif
+ ArtPoint *pts;
+
+#ifdef VERBOSE
+ printf ("fix_crossing: [%d..%d)", start, end);
+ for (k = 0; k < n_active_segs; k++)
+ printf (" %d", active_segs[k]);
+ printf ("\n");
+#endif
+
+ if (start == -1)
+ return;
+
+ for (i = start + 1; i < end; i++)
+ {
+
+ asi = active_segs[i];
+ if (cursor[asi] < vp->segs[asi].n_points - 1) {
+ p0i = ips[asi][0];
+ if (n_ips[asi] == 1)
+ p1i = vp->segs[asi].points[cursor[asi] + 1];
+ else
+ p1i = ips[asi][1];
+
+ for (j = i - 1; j >= start; j--)
+ {
+ asj = active_segs[j];
+ if (cursor[asj] < vp->segs[asj].n_points - 1)
+ {
+ p0j = ips[asj][0];
+ if (n_ips[asj] == 1)
+ p1j = vp->segs[asj].points[cursor[asj] + 1];
+ else
+ p1j = ips[asj][1];
+
+ /* we _hope_ p0i = p0j */
+ if (x_order_2 (p0j, p1j, p0i, p1i) == -1)
+ break;
+ }
+ }
+
+ target = j + 1;
+ /* target is where active_seg[i] _should_ be in active_segs */
+
+ if (target != i)
+ {
+ swap = 1;
+
+#ifdef VERBOSE
+ printf ("fix_crossing: at %i should be %i\n", i, target);
+#endif
+
+ /* let's close off all relevant segments */
+ for (j = i; j >= target; j--)
+ {
+ asi = active_segs[j];
+ /* First conjunct: this isn't the last point in the original
+ segment.
+
+ Second conjunct: this isn't the first point in the new
+ segment (i.e. already broken).
+ */
+ if (cursor[asi] < vp->segs[asi].n_points - 1 &&
+ (*p_new_vp)->segs[seg_map[asi]].n_points != 1)
+ {
+ int seg_num;
+ /* so break here */
+#ifdef VERBOSE
+ printf ("closing off %d\n", j);
+#endif
+
+ pts = art_new (ArtPoint, 16);
+ pts[0] = ips[asi][0];
+ seg_num = art_svp_add_segment (p_new_vp, pn_segs_max,
+ pn_points_max,
+ 1, vp->segs[asi].dir,
+ pts,
+ NULL);
+ (*pn_points_max)[seg_num] = 16;
+ seg_map[asi] = seg_num;
+ }
+ }
+
+ /* now fix the ordering in active_segs */
+ asi = active_segs[i];
+ for (j = i; j > target; j--)
+ active_segs[j] = active_segs[j - 1];
+ active_segs[j] = asi;
+ }
+ }
+ }
+ if (swap && start > 0)
+ {
+ int as_start;
+
+ as_start = active_segs[start];
+ if (cursor[as_start] < vp->segs[as_start].n_points)
+ {
+#ifdef VERBOSE
+ printf ("checking intersection of %d, %d\n", start - 1, start);
+#endif
+ intersect_neighbors (start, active_segs,
+ n_ips, n_ips_max, ips,
+ cursor, vp);
+ }
+ }
+
+ if (swap && end < n_active_segs)
+ {
+ int as_end;
+
+ as_end = active_segs[end - 1];
+ if (cursor[as_end] < vp->segs[as_end].n_points)
+ {
+#ifdef VERBOSE
+ printf ("checking intersection of %d, %d\n", end - 1, end);
+#endif
+ intersect_neighbors (end, active_segs,
+ n_ips, n_ips_max, ips,
+ cursor, vp);
+ }
+ }
+ if (swap)
+ {
+#ifdef VERBOSE
+ printf ("fix_crossing return: [%d..%d)", start, end);
+ for (k = 0; k < n_active_segs; k++)
+ printf (" %d", active_segs[k]);
+ printf ("\n");
+#endif
+ }
+}
+
+/* Return a new sorted vector that covers the same area as the
+ argument, but which satisfies the nocross invariant.
+
+ Basically, this routine works by finding the intersection points,
+ and cutting the segments at those points.
+
+ Status of this routine:
+
+ Basic correctness: Seems ok.
+
+ Numerical stability: known problems in the case of points falling
+ on lines, and colinear lines. For actual use, randomly perturbing
+ the vertices is currently recommended.
+
+ Speed: pretty good, although a more efficient priority queue, as
+ well as bbox culling of potential intersections, are two
+ optimizations that could help.
+
+ Precision: pretty good, although the numerical stability problems
+ make this routine unsuitable for precise calculations of
+ differences.
+
+*/
+
+/* Here is a more detailed description of the algorithm. It follows
+ roughly the structure of traverse (above), but is obviously quite
+ a bit more complex.
+
+ Here are a few important data structures:
+
+ A new sorted vector path (new_svp).
+
+ For each (active) segment in the original, a list of intersection
+ points.
+
+ Of course, the original being traversed.
+
+ The following invariants hold (in addition to the invariants
+ of the traverse procedure).
+
+ The new sorted vector path lies entirely above the y scan line.
+
+ The new sorted vector path keeps the nocross invariant.
+
+ For each active segment, the y scan line crosses the line from the
+ first to the second of the intersection points (where the second
+ point is cursor + 1 if there is only one intersection point).
+
+ The list of intersection points + the (cursor + 1) point is kept
+ in nondecreasing y order.
+
+ Of the active segments, none of the lines from first to second
+ intersection point cross the 1st ip..2nd ip line of the left or
+ right neighbor. (However, such a line may cross further
+ intersection points of the neighbors, or segments past the
+ immediate neighbors).
+
+ Of the active segments, all lines from 1st ip..2nd ip are in
+ strictly increasing x_order (this is very similar to the invariant
+ of the traverse procedure, but is explicitly stated here in terms
+ of ips). (this basically says that nocross holds on the active
+ segments)
+
+ The combination of the new sorted vector path, the path through all
+ the intersection points to cursor + 1, and [cursor + 1, n_points)
+ covers the same area as the argument.
+
+ Another important data structure is mapping from original segment
+ number to new segment number.
+
+ The algorithm is perhaps best understood as advancing the cursors
+ while maintaining these invariants. Here's roughly how it's done.
+
+ When deleting segments from the active list, those segments are added
+ to the new sorted vector path. In addition, the neighbors may intersect
+ each other, so they are intersection tested (see below).
+
+ When inserting new segments, they are intersection tested against
+ their neighbors. The top point of the segment becomes the first
+ intersection point.
+
+ Advancing the cursor is just a bit different from the traverse
+ routine, as the cursor may advance through the intersection points
+ as well. Only when there is a single intersection point in the list
+ does the cursor advance in the original segment. In either case,
+ the new vector is intersection tested against both neighbors. It
+ also causes the vector over which the cursor is advancing to be
+ added to the new svp.
+
+ Two steps need further clarification:
+
+ Intersection testing: the 1st ip..2nd ip lines of the neighbors
+ are tested to see if they cross (using intersect_lines). If so,
+ then the intersection point is added to the ip list of both
+ segments, maintaining the invariant that the list of intersection
+ points is nondecreasing in y).
+
+ Adding vector to new svp: if the new vector shares a top x
+ coordinate with another vector, then it is checked to see whether
+ it is in order. If not, then both segments are "broken," and then
+ restarted. Note: in the case when both segments are in the same
+ order, they may simply be swapped without breaking.
+
+ For the time being, I'm going to put some of these operations into
+ subroutines. If it turns out to be a performance problem, I could
+ try to reorganize the traverse procedure so that each is only
+ called once, and inline them. But if it's not a performance
+ problem, I'll just keep it this way, because it will probably help
+ to make the code clearer, and I believe this code could use all the
+ clarity it can get. */
+/**
+ * art_svp_uncross: Resolve self-intersections of an svp.
+ * @vp: The original svp.
+ *
+ * Finds all the intersections within @vp, and constructs a new svp
+ * with new points added at these intersections.
+ *
+ * This routine needs to be redone from scratch with numerical robustness
+ * in mind. I'm working on it.
+ *
+ * Return value: The new svp.
+ **/
+ArtSVP *
+art_svp_uncross (ArtSVP *vp)
+{
+ int *active_segs;
+ int n_active_segs;
+ int *cursor;
+ int seg_idx;
+ double y;
+ int tmp1, tmp2;
+ int asi;
+ int i, j;
+ /* new data structures */
+ /* intersection points; invariant: *ips[i] is only allocated if
+ i is active */
+ int *n_ips, *n_ips_max;
+ ArtPoint **ips;
+ /* new sorted vector path */
+ int n_segs_max, seg_num;
+ ArtSVP *new_vp;
+ int *n_points_max;
+ /* mapping from argument to new segment numbers - again, only valid
+ if active */
+ int *seg_map;
+ double y_curs;
+ ArtPoint p_curs;
+ int first_share;
+ double share_x;
+ ArtPoint *pts;
+
+ n_segs_max = 16;
+ new_vp = (ArtSVP *)art_alloc (sizeof(ArtSVP) +
+ (n_segs_max - 1) * sizeof(ArtSVPSeg));
+ new_vp->n_segs = 0;
+
+ if (vp->n_segs == 0)
+ return new_vp;
+
+ active_segs = art_new (int, vp->n_segs);
+ cursor = art_new (int, vp->n_segs);
+
+ seg_map = art_new (int, vp->n_segs);
+ n_ips = art_new (int, vp->n_segs);
+ n_ips_max = art_new (int, vp->n_segs);
+ ips = art_new (ArtPoint *, vp->n_segs);
+
+ n_points_max = art_new (int, n_segs_max);
+
+ n_active_segs = 0;
+ seg_idx = 0;
+ y = vp->segs[0].points[0].y;
+ while (seg_idx < vp->n_segs || n_active_segs > 0)
+ {
+#ifdef VERBOSE
+ printf ("y = %g\n", y);
+#endif
+
+ /* maybe move deletions to end of loop (to avoid so much special
+ casing on the end of a segment)? */
+
+ /* delete segments ending at y from active list */
+ for (i = 0; i < n_active_segs; i++)
+ {
+ asi = active_segs[i];
+ if (vp->segs[asi].n_points - 1 == cursor[asi] &&
+ vp->segs[asi].points[cursor[asi]].y == y)
+ {
+ do
+ {
+#ifdef VERBOSE
+ printf ("deleting %d\n", asi);
+#endif
+ art_free (ips[asi]);
+ n_active_segs--;
+ for (j = i; j < n_active_segs; j++)
+ active_segs[j] = active_segs[j + 1];
+ if (i < n_active_segs)
+ asi = active_segs[i];
+ else
+ break;
+ }
+ while (vp->segs[asi].n_points - 1 == cursor[asi] &&
+ vp->segs[asi].points[cursor[asi]].y == y);
+
+ /* test intersection of neighbors */
+ if (i > 0 && i < n_active_segs)
+ intersect_neighbors (i, active_segs,
+ n_ips, n_ips_max, ips,
+ cursor, vp);
+
+ i--;
+ }
+ }
+
+ /* insert new segments into the active list */
+ while (seg_idx < vp->n_segs && y == vp->segs[seg_idx].points[0].y)
+ {
+#ifdef VERBOSE
+ printf ("inserting %d\n", seg_idx);
+#endif
+ cursor[seg_idx] = 0;
+ for (i = 0; i < n_active_segs; i++)
+ {
+ asi = active_segs[i];
+ if (x_order_2 (vp->segs[seg_idx].points[0],
+ vp->segs[seg_idx].points[1],
+ vp->segs[asi].points[cursor[asi]],
+ vp->segs[asi].points[cursor[asi] + 1]) == -1)
+ break;
+ }
+
+ /* Create and initialize the intersection points data structure */
+ n_ips[seg_idx] = 1;
+ n_ips_max[seg_idx] = 2;
+ ips[seg_idx] = art_new (ArtPoint, n_ips_max[seg_idx]);
+ ips[seg_idx][0] = vp->segs[seg_idx].points[0];
+
+ /* Start a new segment in the new vector path */
+ pts = art_new (ArtPoint, 16);
+ pts[0] = vp->segs[seg_idx].points[0];
+ seg_num = art_svp_add_segment (&new_vp, &n_segs_max,
+ &n_points_max,
+ 1, vp->segs[seg_idx].dir,
+ pts,
+ NULL);
+ n_points_max[seg_num] = 16;
+ seg_map[seg_idx] = seg_num;
+
+ tmp1 = seg_idx;
+ for (j = i; j < n_active_segs; j++)
+ {
+ tmp2 = active_segs[j];
+ active_segs[j] = tmp1;
+ tmp1 = tmp2;
+ }
+ active_segs[n_active_segs] = tmp1;
+ n_active_segs++;
+
+ if (i > 0)
+ intersect_neighbors (i, active_segs,
+ n_ips, n_ips_max, ips,
+ cursor, vp);
+
+ if (i + 1 < n_active_segs)
+ intersect_neighbors (i + 1, active_segs,
+ n_ips, n_ips_max, ips,
+ cursor, vp);
+
+ seg_idx++;
+ }
+
+ /* all active segs cross the y scanline (considering segs to be
+ closed on top and open on bottom) */
+#ifdef VERBOSE
+ for (i = 0; i < n_active_segs; i++)
+ {
+ asi = active_segs[i];
+ printf ("%d ", asi);
+ for (j = 0; j < n_ips[asi]; j++)
+ printf ("(%g, %g) - ",
+ ips[asi][j].x,
+ ips[asi][j].y);
+ printf ("(%g, %g) %s\n",
+ vp->segs[asi].points[cursor[asi] + 1].x,
+ vp->segs[asi].points[cursor[asi] + 1].y,
+ vp->segs[asi].dir ? "v" : "^");
+ }
+#endif
+
+ /* advance y to the next event
+ Note: this is quadratic. We'd probably get decent constant
+ factor speed improvement by caching the y_curs values. */
+ if (n_active_segs == 0)
+ {
+ if (seg_idx < vp->n_segs)
+ y = vp->segs[seg_idx].points[0].y;
+ /* else we're done */
+ }
+ else
+ {
+ asi = active_segs[0];
+ if (n_ips[asi] == 1)
+ y = vp->segs[asi].points[cursor[asi] + 1].y;
+ else
+ y = ips[asi][1].y;
+ for (i = 1; i < n_active_segs; i++)
+ {
+ asi = active_segs[i];
+ if (n_ips[asi] == 1)
+ y_curs = vp->segs[asi].points[cursor[asi] + 1].y;
+ else
+ y_curs = ips[asi][1].y;
+ if (y > y_curs)
+ y = y_curs;
+ }
+ if (seg_idx < vp->n_segs && y > vp->segs[seg_idx].points[0].y)
+ y = vp->segs[seg_idx].points[0].y;
+ }
+
+ first_share = -1;
+ share_x = 0; /* to avoid gcc warning, although share_x is never
+ used when first_share is -1 */
+ /* advance cursors to reach new y */
+ for (i = 0; i < n_active_segs; i++)
+ {
+ asi = active_segs[i];
+ if (n_ips[asi] == 1)
+ p_curs = vp->segs[asi].points[cursor[asi] + 1];
+ else
+ p_curs = ips[asi][1];
+ if (p_curs.y == y)
+ {
+ svp_add_point (new_vp, n_points_max,
+ p_curs, seg_map, active_segs, n_active_segs, i);
+
+ n_ips[asi]--;
+ for (j = 0; j < n_ips[asi]; j++)
+ ips[asi][j] = ips[asi][j + 1];
+
+ if (n_ips[asi] == 0)
+ {
+ ips[asi][0] = p_curs;
+ n_ips[asi] = 1;
+ cursor[asi]++;
+ }
+
+ if (first_share < 0 || p_curs.x != share_x)
+ {
+ /* this is where crossings are detected, and if
+ found, the active segments switched around. */
+
+ fix_crossing (first_share, i,
+ active_segs, n_active_segs,
+ cursor, ips, n_ips, n_ips_max, vp, seg_map,
+ &new_vp,
+ &n_segs_max, &n_points_max);
+
+ first_share = i;
+ share_x = p_curs.x;
+ }
+
+ if (cursor[asi] < vp->segs[asi].n_points - 1)
+ {
+
+ if (i > 0)
+ intersect_neighbors (i, active_segs,
+ n_ips, n_ips_max, ips,
+ cursor, vp);
+
+ if (i + 1 < n_active_segs)
+ intersect_neighbors (i + 1, active_segs,
+ n_ips, n_ips_max, ips,
+ cursor, vp);
+ }
+ }
+ else
+ {
+ /* not on a cursor point */
+ fix_crossing (first_share, i,
+ active_segs, n_active_segs,
+ cursor, ips, n_ips, n_ips_max, vp, seg_map,
+ &new_vp,
+ &n_segs_max, &n_points_max);
+ first_share = -1;
+ }
+ }
+
+ /* fix crossing on last shared group */
+ fix_crossing (first_share, i,
+ active_segs, n_active_segs,
+ cursor, ips, n_ips, n_ips_max, vp, seg_map,
+ &new_vp,
+ &n_segs_max, &n_points_max);
+
+#ifdef VERBOSE
+ printf ("\n");
+#endif
+ }
+
+ /* not necessary to sort, new segments only get added at y, which
+ increases monotonically */
+#if 0
+ qsort (&new_vp->segs, new_vp->n_segs, sizeof (svp_seg), svp_seg_compare);
+ {
+ int k;
+ for (k = 0; k < new_vp->n_segs - 1; k++)
+ {
+ printf ("(%g, %g) - (%g, %g) %s (%g, %g) - (%g, %g)\n",
+ new_vp->segs[k].points[0].x,
+ new_vp->segs[k].points[0].y,
+ new_vp->segs[k].points[1].x,
+ new_vp->segs[k].points[1].y,
+ svp_seg_compare (&new_vp->segs[k], &new_vp->segs[k + 1]) > 1 ? ">": "<",
+ new_vp->segs[k + 1].points[0].x,
+ new_vp->segs[k + 1].points[0].y,
+ new_vp->segs[k + 1].points[1].x,
+ new_vp->segs[k + 1].points[1].y);
+ }
+ }
+#endif
+
+ art_free (n_points_max);
+ art_free (seg_map);
+ art_free (n_ips_max);
+ art_free (n_ips);
+ art_free (ips);
+ art_free (cursor);
+ art_free (active_segs);
+
+ return new_vp;
+}
+
+#define noVERBOSE
+
+/* Rewind a svp satisfying the nocross invariant.
+
+ The winding number of a segment is defined as the winding number of
+ the points to the left while travelling in the direction of the
+ segment. Therefore it preincrements and postdecrements as a scan
+ line is traversed from left to right.
+
+ Status of this routine:
+
+ Basic correctness: Was ok in gfonted. However, this code does not
+ yet compute bboxes for the resulting svp segs.
+
+ Numerical stability: known problems in the case of horizontal
+ segments in polygons with any complexity. For actual use, randomly
+ perturbing the vertices is recommended.
+
+ Speed: good.
+
+ Precision: good, except that no attempt is made to remove "hair".
+ Doing random perturbation just makes matters worse.
+
+*/
+/**
+ * art_svp_rewind_uncrossed: Rewind an svp satisfying the nocross invariant.
+ * @vp: The original svp.
+ * @rule: The winding rule.
+ *
+ * Creates a new svp with winding number of 0 or 1 everywhere. The @rule
+ * argument specifies a rule for how winding numbers in the original
+ * @vp map to the winding numbers in the result.
+ *
+ * With @rule == ART_WIND_RULE_NONZERO, the resulting svp has a
+ * winding number of 1 where @vp has a nonzero winding number.
+ *
+ * With @rule == ART_WIND_RULE_INTERSECT, the resulting svp has a
+ * winding number of 1 where @vp has a winding number greater than
+ * 1. It is useful for computing intersections.
+ *
+ * With @rule == ART_WIND_RULE_ODDEVEN, the resulting svp has a
+ * winding number of 1 where @vp has an odd winding number. It is
+ * useful for implementing the even-odd winding rule of the
+ * PostScript imaging model.
+ *
+ * With @rule == ART_WIND_RULE_POSITIVE, the resulting svp has a
+ * winding number of 1 where @vp has a positive winding number. It is
+ * useful for implementing asymmetric difference.
+ *
+ * This routine needs to be redone from scratch with numerical robustness
+ * in mind. I'm working on it.
+ *
+ * Return value: The new svp.
+ **/
+ArtSVP *
+art_svp_rewind_uncrossed (ArtSVP *vp, ArtWindRule rule)
+{
+ int *active_segs;
+ int n_active_segs;
+ int *cursor;
+ int seg_idx;
+ double y;
+ int tmp1, tmp2;
+ int asi;
+ int i, j;
+
+ ArtSVP *new_vp;
+ int n_segs_max;
+ int *winding;
+ int left_wind;
+ int wind;
+ int keep, invert;
+
+#ifdef VERBOSE
+ print_svp (vp);
+#endif
+ n_segs_max = 16;
+ new_vp = (ArtSVP *)art_alloc (sizeof(ArtSVP) +
+ (n_segs_max - 1) * sizeof(ArtSVPSeg));
+ new_vp->n_segs = 0;
+
+ if (vp->n_segs == 0)
+ return new_vp;
+
+ winding = art_new (int, vp->n_segs);
+
+ active_segs = art_new (int, vp->n_segs);
+ cursor = art_new (int, vp->n_segs);
+
+ n_active_segs = 0;
+ seg_idx = 0;
+ y = vp->segs[0].points[0].y;
+ while (seg_idx < vp->n_segs || n_active_segs > 0)
+ {
+#ifdef VERBOSE
+ printf ("y = %g\n", y);
+#endif
+ /* delete segments ending at y from active list */
+ for (i = 0; i < n_active_segs; i++)
+ {
+ asi = active_segs[i];
+ if (vp->segs[asi].n_points - 1 == cursor[asi] &&
+ vp->segs[asi].points[cursor[asi]].y == y)
+ {
+#ifdef VERBOSE
+ printf ("deleting %d\n", asi);
+#endif
+ n_active_segs--;
+ for (j = i; j < n_active_segs; j++)
+ active_segs[j] = active_segs[j + 1];
+ i--;
+ }
+ }
+
+ /* insert new segments into the active list */
+ while (seg_idx < vp->n_segs && y == vp->segs[seg_idx].points[0].y)
+ {
+#ifdef VERBOSE
+ printf ("inserting %d\n", seg_idx);
+#endif
+ cursor[seg_idx] = 0;
+ for (i = 0; i < n_active_segs; i++)
+ {
+ asi = active_segs[i];
+ if (x_order_2 (vp->segs[seg_idx].points[0],
+ vp->segs[seg_idx].points[1],
+ vp->segs[asi].points[cursor[asi]],
+ vp->segs[asi].points[cursor[asi] + 1]) == -1)
+ break;
+ }
+
+ /* Determine winding number for this segment */
+ if (i == 0)
+ left_wind = 0;
+ else if (vp->segs[active_segs[i - 1]].dir)
+ left_wind = winding[active_segs[i - 1]];
+ else
+ left_wind = winding[active_segs[i - 1]] - 1;
+
+ if (vp->segs[seg_idx].dir)
+ wind = left_wind + 1;
+ else
+ wind = left_wind;
+
+ winding[seg_idx] = wind;
+
+ switch (rule)
+ {
+ case ART_WIND_RULE_NONZERO:
+ keep = (wind == 1 || wind == 0);
+ invert = (wind == 0);
+ break;
+ case ART_WIND_RULE_INTERSECT:
+ keep = (wind == 2);
+ invert = 0;
+ break;
+ case ART_WIND_RULE_ODDEVEN:
+ keep = 1;
+ invert = !(wind & 1);
+ break;
+ case ART_WIND_RULE_POSITIVE:
+ keep = (wind == 1);
+ invert = 0;
+ break;
+ default:
+ keep = 0;
+ invert = 0;
+ break;
+ }
+
+ if (keep)
+ {
+ ArtPoint *points, *new_points;
+ int n_points;
+ int new_dir;
+
+#ifdef VERBOSE
+ printf ("keeping segment %d\n", seg_idx);
+#endif
+ n_points = vp->segs[seg_idx].n_points;
+ points = vp->segs[seg_idx].points;
+ new_points = art_new (ArtPoint, n_points);
+ memcpy (new_points, points, n_points * sizeof (ArtPoint));
+ new_dir = vp->segs[seg_idx].dir ^ invert;
+ art_svp_add_segment (&new_vp, &n_segs_max,
+ NULL,
+ n_points, new_dir, new_points,
+ &vp->segs[seg_idx].bbox);
+ }
+
+ tmp1 = seg_idx;
+ for (j = i; j < n_active_segs; j++)
+ {
+ tmp2 = active_segs[j];
+ active_segs[j] = tmp1;
+ tmp1 = tmp2;
+ }
+ active_segs[n_active_segs] = tmp1;
+ n_active_segs++;
+ seg_idx++;
+ }
+
+#ifdef VERBOSE
+ /* all active segs cross the y scanline (considering segs to be
+ closed on top and open on bottom) */
+ for (i = 0; i < n_active_segs; i++)
+ {
+ asi = active_segs[i];
+ printf ("%d:%d (%g, %g) - (%g, %g) %s %d\n", asi,
+ cursor[asi],
+ vp->segs[asi].points[cursor[asi]].x,
+ vp->segs[asi].points[cursor[asi]].y,
+ vp->segs[asi].points[cursor[asi] + 1].x,
+ vp->segs[asi].points[cursor[asi] + 1].y,
+ vp->segs[asi].dir ? "v" : "^",
+ winding[asi]);
+ }
+#endif
+
+ /* advance y to the next event */
+ if (n_active_segs == 0)
+ {
+ if (seg_idx < vp->n_segs)
+ y = vp->segs[seg_idx].points[0].y;
+ /* else we're done */
+ }
+ else
+ {
+ asi = active_segs[0];
+ y = vp->segs[asi].points[cursor[asi] + 1].y;
+ for (i = 1; i < n_active_segs; i++)
+ {
+ asi = active_segs[i];
+ if (y > vp->segs[asi].points[cursor[asi] + 1].y)
+ y = vp->segs[asi].points[cursor[asi] + 1].y;
+ }
+ if (seg_idx < vp->n_segs && y > vp->segs[seg_idx].points[0].y)
+ y = vp->segs[seg_idx].points[0].y;
+ }
+
+ /* advance cursors to reach new y */
+ for (i = 0; i < n_active_segs; i++)
+ {
+ asi = active_segs[i];
+ while (cursor[asi] < vp->segs[asi].n_points - 1 &&
+ y >= vp->segs[asi].points[cursor[asi] + 1].y)
+ cursor[asi]++;
+ }
+#ifdef VERBOSE
+ printf ("\n");
+#endif
+ }
+ art_free (cursor);
+ art_free (active_segs);
+ art_free (winding);
+
+ return new_vp;
+}
diff -Nru swftools-0.9.2+ds1/lib/art/art_svp_wind.h swftools-0.9.1/lib/art/art_svp_wind.h
--- swftools-0.9.2+ds1/lib/art/art_svp_wind.h 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/art/art_svp_wind.h 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,57 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __ART_SVP_WIND_H__
+#define __ART_SVP_WIND_H__
+
+/* Primitive intersection and winding number operations on sorted
+ vector paths. */
+
+#ifdef LIBART_COMPILATION
+#include "art_svp.h"
+#else
+#include "art_svp.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#ifndef ART_WIND_RULE_DEFINED
+#define ART_WIND_RULE_DEFINED
+typedef enum {
+ ART_WIND_RULE_NONZERO,
+ ART_WIND_RULE_INTERSECT,
+ ART_WIND_RULE_ODDEVEN,
+ ART_WIND_RULE_POSITIVE
+} ArtWindRule;
+#endif
+
+ArtSVP *
+art_svp_uncross (ArtSVP *vp);
+
+ArtSVP *
+art_svp_rewind_uncrossed (ArtSVP *vp, ArtWindRule rule);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __ART_SVP_WIND_H__ */
diff -Nru swftools-0.9.2+ds1/lib/art/art_uta.c swftools-0.9.1/lib/art/art_uta.c
--- swftools-0.9.2+ds1/lib/art/art_uta.c 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/art/art_uta.c 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,88 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+#include "art_uta.h"
+
+#include
+#include "art_misc.h"
+
+/**
+ * art_uta_new: Allocate a new uta.
+ * @x0: Left coordinate of uta.
+ * @y0: Top coordinate of uta.
+ * @x1: Right coordinate of uta.
+ * @y1: Bottom coordinate of uta.
+ *
+ * Allocates a new microtile array. The arguments are in units of
+ * tiles, not pixels.
+ *
+ * Returns: the newly allocated #ArtUta.
+ **/
+ArtUta *
+art_uta_new (int x0, int y0, int x1, int y1)
+{
+ ArtUta *uta;
+
+ uta = art_new (ArtUta, 1);
+ uta->x0 = x0;
+ uta->y0 = y0;
+ uta->width = x1 - x0;
+ uta->height = y1 - y0;
+
+ uta->utiles = art_new (ArtUtaBbox, uta->width * uta->height);
+
+ memset (uta->utiles, 0, uta->width * uta->height * sizeof(ArtUtaBbox));
+ return uta;
+ }
+
+/**
+ * art_uta_new_coords: Allocate a new uta, based on pixel coordinates.
+ * @x0: Left coordinate of uta.
+ * @y0: Top coordinate of uta.
+ * @x1: Right coordinate of uta.
+ * @y1: Bottom coordinate of uta.
+ *
+ * Allocates a new microtile array. The arguments are in pixels
+ *
+ * Returns: the newly allocated #ArtUta.
+ **/
+ArtUta *
+art_uta_new_coords (int x0, int y0, int x1, int y1)
+{
+ return art_uta_new (x0 >> ART_UTILE_SHIFT, y0 >> ART_UTILE_SHIFT,
+ 1 + (x1 >> ART_UTILE_SHIFT),
+ 1 + (y1 >> ART_UTILE_SHIFT));
+}
+
+/**
+ * art_uta_free: Free a uta.
+ * @uta: The uta to free.
+ *
+ * Frees the microtile array structure, including the actual microtile
+ * data.
+ **/
+void
+art_uta_free (ArtUta *uta)
+{
+ art_free (uta->utiles);
+ art_free (uta);
+}
+
+/* User to Aardvark! */
diff -Nru swftools-0.9.2+ds1/lib/art/art_uta.h swftools-0.9.1/lib/art/art_uta.h
--- swftools-0.9.2+ds1/lib/art/art_uta.h 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/art/art_uta.h 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,72 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __ART_UTA_H__
+#define __ART_UTA_H__
+
+/* Basic data structures and constructors for microtile arrays */
+
+#ifdef LIBART_COMPILATION
+#include "art_misc.h"
+#else
+#include "art_misc.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+typedef art_u32 ArtUtaBbox;
+typedef struct _ArtUta ArtUta;
+
+#define ART_UTA_BBOX_CONS(x0, y0, x1, y1) (((x0) << 24) | ((y0) << 16) | \
+ ((x1) << 8) | (y1))
+
+#define ART_UTA_BBOX_X0(ub) ((ub) >> 24)
+#define ART_UTA_BBOX_Y0(ub) (((ub) >> 16) & 0xff)
+#define ART_UTA_BBOX_X1(ub) (((ub) >> 8) & 0xff)
+#define ART_UTA_BBOX_Y1(ub) ((ub) & 0xff)
+
+#define ART_UTILE_SHIFT 5
+#define ART_UTILE_SIZE (1 << ART_UTILE_SHIFT)
+
+/* Coordinates are shifted right by ART_UTILE_SHIFT wrt the real
+ coordinates. */
+struct _ArtUta {
+ int x0;
+ int y0;
+ int width;
+ int height;
+ ArtUtaBbox *utiles;
+};
+
+ArtUta *
+art_uta_new (int x0, int y0, int x1, int y1);
+
+ArtUta *
+art_uta_new_coords (int x0, int y0, int x1, int y1);
+
+void
+art_uta_free (ArtUta *uta);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __ART_UTA_H__ */
diff -Nru swftools-0.9.2+ds1/lib/art/art_uta_ops.c swftools-0.9.1/lib/art/art_uta_ops.c
--- swftools-0.9.2+ds1/lib/art/art_uta_ops.c 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/art/art_uta_ops.c 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,112 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998-2000 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+#include "art_uta_ops.h"
+
+#include
+#include "art_misc.h"
+#include "art_uta.h"
+
+#ifndef MIN
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+#endif
+
+#ifndef MAX
+#define MAX(a,b) ((a) > (b) ? (a) : (b))
+#endif
+
+/**
+ * art_uta_union: Compute union of two uta's.
+ * @uta1: One uta.
+ * @uta2: The other uta.
+ *
+ * Computes the union of @uta1 and @uta2. The union is approximate,
+ * but coverage is guaranteed over all pixels included in either of
+ * the arguments, ie more pixels may be covered than the "exact"
+ * union.
+ *
+ * Note: this routine is used in the Gnome Canvas to accumulate the
+ * region that needs to be repainted. However, since it copies over
+ * the entire uta (which might be largish) even when the update may be
+ * small, it can be a performance bottleneck. There are two approaches
+ * to this problem, both of which are probably worthwhile. First, the
+ * generated uta's should always be limited to the visible window,
+ * thus guaranteeing that uta's never become large. Second, there
+ * should be a new, destructive union operation that only touches a
+ * small part of the uta when the update is small.
+ *
+ * Return value: The new union uta.
+ **/
+ArtUta *
+art_uta_union (ArtUta *uta1, ArtUta *uta2)
+{
+ ArtUta *uta;
+ int x0, y0, x1, y1;
+ int x, y;
+ int ix, ix1, ix2;
+ ArtUtaBbox bb, bb1, bb2;
+
+ x0 = MIN(uta1->x0, uta2->x0);
+ y0 = MIN(uta1->y0, uta2->y0);
+ x1 = MAX(uta1->x0 + uta1->width, uta2->x0 + uta2->width);
+ y1 = MAX(uta1->y0 + uta1->height, uta2->y0 + uta2->height);
+ uta = art_uta_new (x0, y0, x1, y1);
+
+ /* could move the first two if/else statements out of the loop */
+ ix = 0;
+ for (y = y0; y < y1; y++)
+ {
+ ix1 = (y - uta1->y0) * uta1->width + x0 - uta1->x0;
+ ix2 = (y - uta2->y0) * uta2->width + x0 - uta2->x0;
+ for (x = x0; x < x1; x++)
+ {
+ if (x < uta1->x0 || y < uta1->y0 ||
+ x >= uta1->x0 + uta1->width || y >= uta1->y0 + uta1->height)
+ bb1 = 0;
+ else
+ bb1 = uta1->utiles[ix1];
+
+ if (x < uta2->x0 || y < uta2->y0 ||
+ x >= uta2->x0 + uta2->width || y >= uta2->y0 + uta2->height)
+ bb2 = 0;
+ else
+ bb2 = uta2->utiles[ix2];
+
+ if (bb1 == 0)
+ bb = bb2;
+ else if (bb2 == 0)
+ bb = bb1;
+ else
+ bb = ART_UTA_BBOX_CONS(MIN(ART_UTA_BBOX_X0(bb1),
+ ART_UTA_BBOX_X0(bb2)),
+ MIN(ART_UTA_BBOX_Y0(bb1),
+ ART_UTA_BBOX_Y0(bb2)),
+ MAX(ART_UTA_BBOX_X1(bb1),
+ ART_UTA_BBOX_X1(bb2)),
+ MAX(ART_UTA_BBOX_Y1(bb1),
+ ART_UTA_BBOX_Y1(bb2)));
+ uta->utiles[ix] = bb;
+ ix++;
+ ix1++;
+ ix2++;
+ }
+ }
+ return uta;
+}
diff -Nru swftools-0.9.2+ds1/lib/art/art_uta_ops.h swftools-0.9.1/lib/art/art_uta_ops.h
--- swftools-0.9.2+ds1/lib/art/art_uta_ops.h 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/art/art_uta_ops.h 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,42 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __ART_UTA_OPS_H__
+#define __ART_UTA_OPS_H__
+
+/* Basic operations on microtile arrays */
+
+#ifdef LIBART_COMPILATION
+#include "art_uta.h"
+#else
+#include "art_uta.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+ArtUta *
+art_uta_union (ArtUta *uta1, ArtUta *uta2);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __ART_UTA_OPS_H__ */
diff -Nru swftools-0.9.2+ds1/lib/art/art_uta_rect.c swftools-0.9.1/lib/art/art_uta_rect.c
--- swftools-0.9.2+ds1/lib/art/art_uta_rect.c 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/art/art_uta_rect.c 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,111 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+#include "art_uta_rect.h"
+
+#include "art_misc.h"
+#include "art_uta.h"
+#include "art_rect.h"
+
+/**
+ * art_uta_from_irect: Generate uta covering a rectangle.
+ * @bbox: The source rectangle.
+ *
+ * Generates a uta exactly covering @bbox. Please do not call this
+ * function with a @bbox with zero height or width.
+ *
+ * Return value: the new uta.
+ **/
+ArtUta *
+art_uta_from_irect (ArtIRect *bbox)
+{
+ ArtUta *uta;
+ ArtUtaBbox *utiles;
+ ArtUtaBbox bb;
+ int width, height;
+ int x, y;
+ int xf0, yf0, xf1, yf1;
+ int ix;
+
+ uta = art_new (ArtUta, 1);
+ uta->x0 = bbox->x0 >> ART_UTILE_SHIFT;
+ uta->y0 = bbox->y0 >> ART_UTILE_SHIFT;
+ width = ((bbox->x1 + ART_UTILE_SIZE - 1) >> ART_UTILE_SHIFT) - uta->x0;
+ height = ((bbox->y1 + ART_UTILE_SIZE - 1) >> ART_UTILE_SHIFT) - uta->y0;
+ utiles = art_new (ArtUtaBbox, width * height);
+
+ uta->width = width;
+ uta->height = height;
+ uta->utiles = utiles;
+
+ xf0 = bbox->x0 & (ART_UTILE_SIZE - 1);
+ yf0 = bbox->y0 & (ART_UTILE_SIZE - 1);
+ xf1 = ((bbox->x1 - 1) & (ART_UTILE_SIZE - 1)) + 1;
+ yf1 = ((bbox->y1 - 1) & (ART_UTILE_SIZE - 1)) + 1;
+ if (height == 1)
+ {
+ if (width == 1)
+ utiles[0] = ART_UTA_BBOX_CONS (xf0, yf0, xf1, yf1);
+ else
+ {
+ utiles[0] = ART_UTA_BBOX_CONS (xf0, yf0, ART_UTILE_SIZE, yf1);
+ bb = ART_UTA_BBOX_CONS (0, yf0, ART_UTILE_SIZE, yf1);
+ for (x = 1; x < width - 1; x++)
+ utiles[x] = bb;
+ utiles[x] = ART_UTA_BBOX_CONS (0, yf0, xf1, yf1);
+ }
+ }
+ else
+ {
+ if (width == 1)
+ {
+ utiles[0] = ART_UTA_BBOX_CONS (xf0, yf0, xf1, ART_UTILE_SIZE);
+ bb = ART_UTA_BBOX_CONS (xf0, 0, xf1, ART_UTILE_SIZE);
+ for (y = 1; y < height - 1; y++)
+ utiles[y] = bb;
+ utiles[y] = ART_UTA_BBOX_CONS (xf0, 0, xf1, yf1);
+ }
+ else
+ {
+ utiles[0] =
+ ART_UTA_BBOX_CONS (xf0, yf0, ART_UTILE_SIZE, ART_UTILE_SIZE);
+ bb = ART_UTA_BBOX_CONS (0, yf0, ART_UTILE_SIZE, ART_UTILE_SIZE);
+ for (x = 1; x < width - 1; x++)
+ utiles[x] = bb;
+ utiles[x] = ART_UTA_BBOX_CONS (0, yf0, xf1, ART_UTILE_SIZE);
+ ix = width;
+ for (y = 1; y < height - 1; y++)
+ {
+ utiles[ix++] =
+ ART_UTA_BBOX_CONS (xf0, 0, ART_UTILE_SIZE, ART_UTILE_SIZE);
+ bb = ART_UTA_BBOX_CONS (0, 0, ART_UTILE_SIZE, ART_UTILE_SIZE);
+ for (x = 1; x < width - 1; x++)
+ utiles[ix++] = bb;
+ utiles[ix++] = ART_UTA_BBOX_CONS (0, 0, xf1, ART_UTILE_SIZE);
+ }
+ utiles[ix++] = ART_UTA_BBOX_CONS (xf0, 0, ART_UTILE_SIZE, yf1);
+ bb = ART_UTA_BBOX_CONS (0, 0, ART_UTILE_SIZE, yf1);
+ for (x = 1; x < width - 1; x++)
+ utiles[ix++] = bb;
+ utiles[ix++] = ART_UTA_BBOX_CONS (0, 0, xf1, yf1);
+ }
+ }
+ return uta;
+}
diff -Nru swftools-0.9.2+ds1/lib/art/art_uta_rect.h swftools-0.9.1/lib/art/art_uta_rect.h
--- swftools-0.9.2+ds1/lib/art/art_uta_rect.h 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/art/art_uta_rect.h 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,42 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __ART_UTA_RECT_H__
+#define __ART_UTA_RECT_H__
+
+#ifdef LIBART_COMPILATION
+#include "art_rect.h"
+#include "art_uta.h"
+#else
+#include "art_rect.h"
+#include "art_uta.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+ArtUta *
+art_uta_from_irect (ArtIRect *bbox);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __ART_UTA_RECT_H__ */
diff -Nru swftools-0.9.2+ds1/lib/art/art_uta_svp.c swftools-0.9.1/lib/art/art_uta_svp.c
--- swftools-0.9.2+ds1/lib/art/art_uta_svp.c 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/art/art_uta_svp.c 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,54 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998-2000 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/* LGPL Copyright 1998 Raph Levien */
+
+#include "config.h"
+#include "art_uta_svp.h"
+
+#include "art_misc.h"
+#include "art_vpath.h"
+#include "art_uta.h"
+#include "art_uta_vpath.h"
+#include "art_svp.h"
+#include "art_vpath_svp.h"
+
+/**
+ * art_uta_from_svp: Generate uta covering an svp.
+ * @svp: The source svp.
+ *
+ * Generates a uta covering @svp. The resulting uta is of course
+ * approximate, ie it may cover more pixels than covered by @svp.
+ *
+ * Note: I will want to replace this with a more direct
+ * implementation. But this gets the api in place.
+ *
+ * Return value: the new uta.
+ **/
+ArtUta *
+art_uta_from_svp (const ArtSVP *svp)
+{
+ ArtVpath *vpath;
+ ArtUta *uta;
+
+ vpath = art_vpath_from_svp (svp);
+ uta = art_uta_from_vpath (vpath);
+ art_free (vpath);
+ return uta;
+}
diff -Nru swftools-0.9.2+ds1/lib/art/art_uta_svp.h swftools-0.9.1/lib/art/art_uta_svp.h
--- swftools-0.9.2+ds1/lib/art/art_uta_svp.h 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/art/art_uta_svp.h 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,45 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __ART_UTA_SVP_H__
+#define __ART_UTA_SVP_H__
+
+/* Basic data structures and constructors for microtile arrays */
+
+#ifdef LIBART_COMPILATION
+#include "art_svp.h"
+#include "art_uta.h"
+#else
+#include "art_svp.h"
+#include "art_uta.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+ArtUta *
+art_uta_from_svp (const ArtSVP *svp);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __ART_UTA_SVP_H__ */
+
diff -Nru swftools-0.9.2+ds1/lib/art/art_uta_vpath.c swftools-0.9.1/lib/art/art_uta_vpath.c
--- swftools-0.9.2+ds1/lib/art/art_uta_vpath.c 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/art/art_uta_vpath.c 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,382 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998-2000 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+#include "art_uta_vpath.h"
+
+#include
+
+#include "art_misc.h"
+#include "art_vpath.h"
+#include "art_uta.h"
+
+#ifndef MAX
+#define MAX(a, b) (((a) > (b)) ? (a) : (b))
+#endif /* MAX */
+
+#ifndef MIN
+#define MIN(a, b) (((a) < (b)) ? (a) : (b))
+#endif /* MIN */
+
+/**
+ * art_uta_add_line: Add a line to the uta.
+ * @uta: The uta to modify.
+ * @x0: X coordinate of line start point.
+ * @y0: Y coordinate of line start point.
+ * @x1: X coordinate of line end point.
+ * @y1: Y coordinate of line end point.
+ * @rbuf: Buffer containing first difference of winding number.
+ * @rbuf_rowstride: Rowstride of @rbuf.
+ *
+ * Add the line (@x0, @y0) - (@x1, @y1) to @uta, and also update the
+ * winding number buffer used for rendering the interior. @rbuf
+ * contains the first partial difference (in the X direction) of the
+ * winding number, measured in grid cells. Thus, each time that a line
+ * crosses a horizontal uta grid line, an entry of @rbuf is
+ * incremented if @y1 > @y0, decremented otherwise.
+ *
+ * Note that edge handling is fairly delicate. Please rtfs for
+ * details.
+ **/
+void
+art_uta_add_line (ArtUta *uta, double x0, double y0, double x1, double y1,
+ int *rbuf, int rbuf_rowstride)
+{
+ int xmin, ymin;
+ double xmax, ymax;
+ int xmaxf, ymaxf;
+ int xmaxc, ymaxc;
+ int xt0, yt0;
+ int xt1, yt1;
+ int xf0, yf0;
+ int xf1, yf1;
+ int ix, ix1;
+ ArtUtaBbox bb;
+
+ xmin = floor (MIN(x0, x1));
+ xmax = MAX(x0, x1);
+ xmaxf = floor (xmax);
+ xmaxc = ceil (xmax);
+ ymin = floor (MIN(y0, y1));
+ ymax = MAX(y0, y1);
+ ymaxf = floor (ymax);
+ ymaxc = ceil (ymax);
+ xt0 = (xmin >> ART_UTILE_SHIFT) - uta->x0;
+ yt0 = (ymin >> ART_UTILE_SHIFT) - uta->y0;
+ xt1 = (xmaxf >> ART_UTILE_SHIFT) - uta->x0;
+ yt1 = (ymaxf >> ART_UTILE_SHIFT) - uta->y0;
+ if (xt0 == xt1 && yt0 == yt1)
+ {
+ /* entirely inside a microtile, this is easy! */
+ xf0 = xmin & (ART_UTILE_SIZE - 1);
+ yf0 = ymin & (ART_UTILE_SIZE - 1);
+ xf1 = (xmaxf & (ART_UTILE_SIZE - 1)) + xmaxc - xmaxf;
+ yf1 = (ymaxf & (ART_UTILE_SIZE - 1)) + ymaxc - ymaxf;
+
+ ix = yt0 * uta->width + xt0;
+ bb = uta->utiles[ix];
+ if (bb == 0)
+ bb = ART_UTA_BBOX_CONS(xf0, yf0, xf1, yf1);
+ else
+ bb = ART_UTA_BBOX_CONS(MIN(ART_UTA_BBOX_X0(bb), xf0),
+ MIN(ART_UTA_BBOX_Y0(bb), yf0),
+ MAX(ART_UTA_BBOX_X1(bb), xf1),
+ MAX(ART_UTA_BBOX_Y1(bb), yf1));
+ uta->utiles[ix] = bb;
+ }
+ else
+ {
+ double dx, dy;
+ int sx, sy;
+
+ dx = x1 - x0;
+ dy = y1 - y0;
+ sx = dx > 0 ? 1 : dx < 0 ? -1 : 0;
+ sy = dy > 0 ? 1 : dy < 0 ? -1 : 0;
+ if (ymin == ymaxf)
+ {
+ /* special case horizontal (dx/dy slope would be infinite) */
+ xf0 = xmin & (ART_UTILE_SIZE - 1);
+ yf0 = ymin & (ART_UTILE_SIZE - 1);
+ xf1 = (xmaxf & (ART_UTILE_SIZE - 1)) + xmaxc - xmaxf;
+ yf1 = (ymaxf & (ART_UTILE_SIZE - 1)) + ymaxc - ymaxf;
+
+ ix = yt0 * uta->width + xt0;
+ ix1 = yt0 * uta->width + xt1;
+ while (ix != ix1)
+ {
+ bb = uta->utiles[ix];
+ if (bb == 0)
+ bb = ART_UTA_BBOX_CONS(xf0, yf0, ART_UTILE_SIZE, yf1);
+ else
+ bb = ART_UTA_BBOX_CONS(MIN(ART_UTA_BBOX_X0(bb), xf0),
+ MIN(ART_UTA_BBOX_Y0(bb), yf0),
+ ART_UTILE_SIZE,
+ MAX(ART_UTA_BBOX_Y1(bb), yf1));
+ uta->utiles[ix] = bb;
+ xf0 = 0;
+ ix++;
+ }
+ bb = uta->utiles[ix];
+ if (bb == 0)
+ bb = ART_UTA_BBOX_CONS(0, yf0, xf1, yf1);
+ else
+ bb = ART_UTA_BBOX_CONS(0,
+ MIN(ART_UTA_BBOX_Y0(bb), yf0),
+ MAX(ART_UTA_BBOX_X1(bb), xf1),
+ MAX(ART_UTA_BBOX_Y1(bb), yf1));
+ uta->utiles[ix] = bb;
+ }
+ else
+ {
+ /* Do a Bresenham-style traversal of the line */
+ double dx_dy;
+ double x, y;
+ double xn, yn;
+
+ /* normalize coordinates to uta origin */
+ x0 -= uta->x0 << ART_UTILE_SHIFT;
+ y0 -= uta->y0 << ART_UTILE_SHIFT;
+ x1 -= uta->x0 << ART_UTILE_SHIFT;
+ y1 -= uta->y0 << ART_UTILE_SHIFT;
+ if (dy < 0)
+ {
+ double tmp;
+
+ tmp = x0;
+ x0 = x1;
+ x1 = tmp;
+
+ tmp = y0;
+ y0 = y1;
+ y1 = tmp;
+
+ dx = -dx;
+ sx = -sx;
+ dy = -dy;
+ /* we leave sy alone, because it would always be 1,
+ and we need it for the rbuf stuff. */
+ }
+ xt0 = ((int)floor (x0) >> ART_UTILE_SHIFT);
+ xt1 = ((int)floor (x1) >> ART_UTILE_SHIFT);
+ /* now [xy]0 is above [xy]1 */
+
+ ix = yt0 * uta->width + xt0;
+ ix1 = yt1 * uta->width + xt1;
+#ifdef VERBOSE
+ printf ("%% ix = %d,%d; ix1 = %d,%d\n", xt0, yt0, xt1, yt1);
+#endif
+
+ dx_dy = dx / dy;
+ x = x0;
+ y = y0;
+ while (ix != ix1)
+ {
+ int dix;
+
+ /* figure out whether next crossing is horizontal or vertical */
+#ifdef VERBOSE
+ printf ("%% %d,%d\n", xt0, yt0);
+#endif
+ yn = (yt0 + 1) << ART_UTILE_SHIFT;
+
+ /* xn is the intercept with bottom edge of this tile. The
+ following expression is careful to result in exactly
+ x1 when yn = y1. */
+ xn = x1 + dx_dy * (yn - y1);
+
+ if (xt0 != (int)floor (xn) >> ART_UTILE_SHIFT)
+ {
+ /* horizontal crossing */
+ xt0 += sx;
+ dix = sx;
+ if (dx > 0)
+ {
+ xn = xt0 << ART_UTILE_SHIFT;
+ yn = y0 + (xn - x0) / dx_dy;
+
+ xf0 = (int)floor (x) & (ART_UTILE_SIZE - 1);
+ xf1 = ART_UTILE_SIZE;
+ }
+ else
+ {
+ xn = (xt0 + 1) << ART_UTILE_SHIFT;
+ yn = y0 + (xn - x0) / dx_dy;
+
+ xf0 = 0;
+ xmaxc = (int)ceil (x);
+ xf1 = xmaxc - ((xt0 + 1) << ART_UTILE_SHIFT);
+ }
+ ymaxf = (int)floor (yn);
+ ymaxc = (int)ceil (yn);
+ yf1 = (ymaxf & (ART_UTILE_SIZE - 1)) + ymaxc - ymaxf;
+ }
+ else
+ {
+ /* vertical crossing */
+ dix = uta->width;
+ xf0 = (int)floor (MIN(x, xn)) & (ART_UTILE_SIZE - 1);
+ xmax = MAX(x, xn);
+ xmaxc = (int)ceil (xmax);
+ xf1 = xmaxc - (xt0 << ART_UTILE_SHIFT);
+ yf1 = ART_UTILE_SIZE;
+
+ if (rbuf != NULL)
+ rbuf[yt0 * rbuf_rowstride + xt0] += sy;
+
+ yt0++;
+ }
+ yf0 = (int)floor (y) & (ART_UTILE_SIZE - 1);
+ bb = uta->utiles[ix];
+ if (bb == 0)
+ bb = ART_UTA_BBOX_CONS(xf0, yf0, xf1, yf1);
+ else
+ bb = ART_UTA_BBOX_CONS(MIN(ART_UTA_BBOX_X0(bb), xf0),
+ MIN(ART_UTA_BBOX_Y0(bb), yf0),
+ MAX(ART_UTA_BBOX_X1(bb), xf1),
+ MAX(ART_UTA_BBOX_Y1(bb), yf1));
+ uta->utiles[ix] = bb;
+
+ x = xn;
+ y = yn;
+ ix += dix;
+ }
+ xmax = MAX(x, x1);
+ xmaxc = ceil (xmax);
+ ymaxc = ceil (y1);
+ xf0 = (int)floor (MIN(x1, x)) & (ART_UTILE_SIZE - 1);
+ yf0 = (int)floor (y) & (ART_UTILE_SIZE - 1);
+ xf1 = xmaxc - (xt0 << ART_UTILE_SHIFT);
+ yf1 = ymaxc - (yt0 << ART_UTILE_SHIFT);
+ bb = uta->utiles[ix];
+ if (bb == 0)
+ bb = ART_UTA_BBOX_CONS(xf0, yf0, xf1, yf1);
+ else
+ bb = ART_UTA_BBOX_CONS(MIN(ART_UTA_BBOX_X0(bb), xf0),
+ MIN(ART_UTA_BBOX_Y0(bb), yf0),
+ MAX(ART_UTA_BBOX_X1(bb), xf1),
+ MAX(ART_UTA_BBOX_Y1(bb), yf1));
+ uta->utiles[ix] = bb;
+ }
+ }
+}
+
+/**
+ * art_uta_from_vpath: Generate uta covering a vpath.
+ * @vec: The source vpath.
+ *
+ * Generates a uta covering @vec. The resulting uta is of course
+ * approximate, ie it may cover more pixels than covered by @vec.
+ *
+ * Return value: the new uta.
+ **/
+ArtUta *
+art_uta_from_vpath (const ArtVpath *vec)
+{
+ ArtUta *uta;
+ ArtIRect bbox;
+ int *rbuf;
+ int i;
+ double x, y;
+ int sum;
+ int xt, yt;
+ ArtUtaBbox *utiles;
+ ArtUtaBbox bb;
+ int width;
+ int height;
+ int ix;
+
+ art_vpath_bbox_irect (vec, &bbox);
+
+ uta = art_uta_new_coords (bbox.x0, bbox.y0, bbox.x1, bbox.y1);
+
+ width = uta->width;
+ height = uta->height;
+ utiles = uta->utiles;
+
+ rbuf = art_new (int, width * height);
+ for (i = 0; i < width * height; i++)
+ rbuf[i] = 0;
+
+ x = 0;
+ y = 0;
+ for (i = 0; vec[i].code != ART_END; i++)
+ {
+ switch (vec[i].code)
+ {
+ case ART_MOVETO:
+ x = vec[i].x;
+ y = vec[i].y;
+ break;
+ case ART_LINETO:
+ art_uta_add_line (uta, vec[i].x, vec[i].y, x, y, rbuf, width);
+ x = vec[i].x;
+ y = vec[i].y;
+ break;
+ default:
+ /* this shouldn't happen */
+ art_free (rbuf);
+ art_free (uta);
+ return NULL;
+ }
+ }
+
+ /* now add in the filling from rbuf */
+ ix = 0;
+ for (yt = 0; yt < height; yt++)
+ {
+ sum = 0;
+ for (xt = 0; xt < width; xt++)
+ {
+ sum += rbuf[ix];
+ /* Nonzero winding rule - others are possible, but hardly
+ worth it. */
+ if (sum != 0)
+ {
+ bb = utiles[ix];
+ bb &= 0xffff0000;
+ bb |= (ART_UTILE_SIZE << 8) | ART_UTILE_SIZE;
+ utiles[ix] = bb;
+ if (xt != width - 1)
+ {
+ bb = utiles[ix + 1];
+ bb &= 0xffff00;
+ bb |= ART_UTILE_SIZE;
+ utiles[ix + 1] = bb;
+ }
+ if (yt != height - 1)
+ {
+ bb = utiles[ix + width];
+ bb &= 0xff0000ff;
+ bb |= ART_UTILE_SIZE << 8;
+ utiles[ix + width] = bb;
+ if (xt != width - 1)
+ {
+ utiles[ix + width + 1] &= 0xffff;
+ }
+ }
+ }
+ ix++;
+ }
+ }
+
+ art_free (rbuf);
+
+ return uta;
+}
diff -Nru swftools-0.9.2+ds1/lib/art/art_uta_vpath.h swftools-0.9.1/lib/art/art_uta_vpath.h
--- swftools-0.9.2+ds1/lib/art/art_uta_vpath.h 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/art/art_uta_vpath.h 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,50 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __ART_UTA_VPATH_H__
+#define __ART_UTA_VPATH_H__
+
+/* Basic data structures and constructors for microtile arrays */
+
+#ifdef LIBART_COMPILATION
+#include "art_uta.h"
+#include "art_vpath.h"
+#else
+#include "art_uta.h"
+#include "art_vpath.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+ArtUta *
+art_uta_from_vpath (const ArtVpath *vec);
+
+/* This is a private function: */
+void
+art_uta_add_line (ArtUta *uta, double x0, double y0, double x1, double y1,
+ int *rbuf, int rbuf_rowstride);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __ART_UTA_VPATH_H__ */
+
diff -Nru swftools-0.9.2+ds1/lib/art/art_vpath_bpath.c swftools-0.9.1/lib/art/art_vpath_bpath.c
--- swftools-0.9.2+ds1/lib/art/art_vpath_bpath.c 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/art/art_vpath_bpath.c 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,328 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/* Basic constructors and operations for bezier paths */
+
+#include "config.h"
+#include "art_vpath_bpath.h"
+
+#include
+
+#include "art_misc.h"
+
+#include "art_bpath.h"
+#include "art_vpath.h"
+
+/* p must be allocated 2^level points. */
+
+/* level must be >= 1 */
+ArtPoint *
+art_bezier_to_vec (double x0, double y0,
+ double x1, double y1,
+ double x2, double y2,
+ double x3, double y3,
+ ArtPoint *p,
+ int level)
+{
+ double x_m, y_m;
+
+#ifdef VERBOSE
+ printf ("bezier_to_vec: %g,%g %g,%g %g,%g %g,%g %d\n",
+ x0, y0, x1, y1, x2, y2, x3, y3, level);
+#endif
+ if (level == 1) {
+ x_m = (x0 + 3 * (x1 + x2) + x3) * 0.125;
+ y_m = (y0 + 3 * (y1 + y2) + y3) * 0.125;
+ p->x = x_m;
+ p->y = y_m;
+ p++;
+ p->x = x3;
+ p->y = y3;
+ p++;
+#ifdef VERBOSE
+ printf ("-> (%g, %g) -> (%g, %g)\n", x_m, y_m, x3, y3);
+#endif
+ } else {
+ double xa1, ya1;
+ double xa2, ya2;
+ double xb1, yb1;
+ double xb2, yb2;
+
+ xa1 = (x0 + x1) * 0.5;
+ ya1 = (y0 + y1) * 0.5;
+ xa2 = (x0 + 2 * x1 + x2) * 0.25;
+ ya2 = (y0 + 2 * y1 + y2) * 0.25;
+ xb1 = (x1 + 2 * x2 + x3) * 0.25;
+ yb1 = (y1 + 2 * y2 + y3) * 0.25;
+ xb2 = (x2 + x3) * 0.5;
+ yb2 = (y2 + y3) * 0.5;
+ x_m = (xa2 + xb1) * 0.5;
+ y_m = (ya2 + yb1) * 0.5;
+#ifdef VERBOSE
+ printf ("%g,%g %g,%g %g,%g %g,%g\n", xa1, ya1, xa2, ya2,
+ xb1, yb1, xb2, yb2);
+#endif
+ p = art_bezier_to_vec (x0, y0, xa1, ya1, xa2, ya2, x_m, y_m, p, level - 1);
+ p = art_bezier_to_vec (x_m, y_m, xb1, yb1, xb2, yb2, x3, y3, p, level - 1);
+ }
+ return p;
+}
+
+#define RENDER_LEVEL 4
+#define RENDER_SIZE (1 << (RENDER_LEVEL))
+
+/**
+ * art_vpath_render_bez: Render a bezier segment into the vpath.
+ * @p_vpath: Where the pointer to the #ArtVpath structure is stored.
+ * @pn_points: Pointer to the number of points in *@p_vpath.
+ * @pn_points_max: Pointer to the number of points allocated.
+ * @x0: X coordinate of starting bezier point.
+ * @y0: Y coordinate of starting bezier point.
+ * @x1: X coordinate of first bezier control point.
+ * @y1: Y coordinate of first bezier control point.
+ * @x2: X coordinate of second bezier control point.
+ * @y2: Y coordinate of second bezier control point.
+ * @x3: X coordinate of ending bezier point.
+ * @y3: Y coordinate of ending bezier point.
+ * @flatness: Flatness control.
+ *
+ * Renders a bezier segment into the vector path, reallocating and
+ * updating *@p_vpath and *@pn_vpath_max as necessary. *@pn_vpath is
+ * incremented by the number of vector points added.
+ *
+ * This step includes (@x0, @y0) but not (@x3, @y3).
+ *
+ * The @flatness argument guides the amount of subdivision. The Adobe
+ * PostScript reference manual defines flatness as the maximum
+ * deviation between the any point on the vpath approximation and the
+ * corresponding point on the "true" curve, and we follow this
+ * definition here. A value of 0.25 should ensure high quality for aa
+ * rendering.
+**/
+static void
+art_vpath_render_bez (ArtVpath **p_vpath, int *pn, int *pn_max,
+ double x0, double y0,
+ double x1, double y1,
+ double x2, double y2,
+ double x3, double y3,
+ double flatness)
+{
+ double x3_0, y3_0;
+ double z3_0_dot;
+ double z1_dot, z2_dot;
+ double z1_perp, z2_perp;
+ double max_perp_sq;
+
+ double x_m, y_m;
+ double xa1, ya1;
+ double xa2, ya2;
+ double xb1, yb1;
+ double xb2, yb2;
+
+ /* It's possible to optimize this routine a fair amount.
+
+ First, once the _dot conditions are met, they will also be met in
+ all further subdivisions. So we might recurse to a different
+ routine that only checks the _perp conditions.
+
+ Second, the distance _should_ decrease according to fairly
+ predictable rules (a factor of 4 with each subdivision). So it might
+ be possible to note that the distance is within a factor of 4 of
+ acceptable, and subdivide once. But proving this might be hard.
+
+ Third, at the last subdivision, x_m and y_m can be computed more
+ expeditiously (as in the routine above).
+
+ Finally, if we were able to subdivide by, say 2 or 3, this would
+ allow considerably finer-grain control, i.e. fewer points for the
+ same flatness tolerance. This would speed things up downstream.
+
+ In any case, this routine is unlikely to be the bottleneck. It's
+ just that I have this undying quest for more speed...
+
+ */
+
+ x3_0 = x3 - x0;
+ y3_0 = y3 - y0;
+
+ /* z3_0_dot is dist z0-z3 squared */
+ z3_0_dot = x3_0 * x3_0 + y3_0 * y3_0;
+
+ if (z3_0_dot < 0.001)
+ {
+ /* if start and end point are almost identical, the flatness tests
+ * don't work properly, so fall back on testing whether both of
+ * the other two control points are the same as the start point,
+ * too.
+ */
+ if (hypot(x1 - x0, y1 - y0) < 0.001
+ && hypot(x2 - x0, y2 - y0) < 0.001)
+ goto nosubdivide;
+ else
+ goto subdivide;
+ }
+
+ /* we can avoid subdivision if:
+
+ z1 has distance no more than flatness from the z0-z3 line
+
+ z1 is no more z0'ward than flatness past z0-z3
+
+ z1 is more z0'ward than z3'ward on the line traversing z0-z3
+
+ and correspondingly for z2 */
+
+ /* perp is distance from line, multiplied by dist z0-z3 */
+ max_perp_sq = flatness * flatness * z3_0_dot;
+
+ z1_perp = (y1 - y0) * x3_0 - (x1 - x0) * y3_0;
+ if (z1_perp * z1_perp > max_perp_sq)
+ goto subdivide;
+
+ z2_perp = (y3 - y2) * x3_0 - (x3 - x2) * y3_0;
+ if (z2_perp * z2_perp > max_perp_sq)
+ goto subdivide;
+
+ z1_dot = (x1 - x0) * x3_0 + (y1 - y0) * y3_0;
+ if (z1_dot < 0 && z1_dot * z1_dot > max_perp_sq)
+ goto subdivide;
+
+ z2_dot = (x3 - x2) * x3_0 + (y3 - y2) * y3_0;
+ if (z2_dot < 0 && z2_dot * z2_dot > max_perp_sq)
+ goto subdivide;
+
+ if (z1_dot + z1_dot > z3_0_dot)
+ goto subdivide;
+
+ if (z2_dot + z2_dot > z3_0_dot)
+ goto subdivide;
+
+
+ nosubdivide:
+ /* don't subdivide */
+ art_vpath_add_point (p_vpath, pn, pn_max,
+ ART_LINETO, x3, y3);
+ return;
+
+ subdivide:
+
+ xa1 = (x0 + x1) * 0.5;
+ ya1 = (y0 + y1) * 0.5;
+ xa2 = (x0 + 2 * x1 + x2) * 0.25;
+ ya2 = (y0 + 2 * y1 + y2) * 0.25;
+ xb1 = (x1 + 2 * x2 + x3) * 0.25;
+ yb1 = (y1 + 2 * y2 + y3) * 0.25;
+ xb2 = (x2 + x3) * 0.5;
+ yb2 = (y2 + y3) * 0.5;
+ x_m = (xa2 + xb1) * 0.5;
+ y_m = (ya2 + yb1) * 0.5;
+#ifdef VERBOSE
+ printf ("%g,%g %g,%g %g,%g %g,%g\n", xa1, ya1, xa2, ya2,
+ xb1, yb1, xb2, yb2);
+#endif
+ art_vpath_render_bez (p_vpath, pn, pn_max,
+ x0, y0, xa1, ya1, xa2, ya2, x_m, y_m, flatness);
+ art_vpath_render_bez (p_vpath, pn, pn_max,
+ x_m, y_m, xb1, yb1, xb2, yb2, x3, y3, flatness);
+}
+
+/**
+ * art_bez_path_to_vec: Create vpath from bezier path.
+ * @bez: Bezier path.
+ * @flatness: Flatness control.
+ *
+ * Creates a vector path closely approximating the bezier path defined by
+ * @bez. The @flatness argument controls the amount of subdivision. In
+ * general, the resulting vpath deviates by at most @flatness pixels
+ * from the "ideal" path described by @bez.
+ *
+ * Return value: Newly allocated vpath.
+ **/
+ArtVpath *
+art_bez_path_to_vec (const ArtBpath *bez, double flatness)
+{
+ ArtVpath *vec;
+ int vec_n, vec_n_max;
+ int bez_index;
+ double x, y;
+
+ vec_n = 0;
+ vec_n_max = RENDER_SIZE;
+ vec = art_new (ArtVpath, vec_n_max);
+
+ /* Initialization is unnecessary because of the precondition that the
+ bezier path does not begin with LINETO or CURVETO, but is here
+ to make the code warning-free. */
+ x = 0;
+ y = 0;
+
+ bez_index = 0;
+ do
+ {
+#ifdef VERBOSE
+ printf ("%s %g %g\n",
+ bez[bez_index].code == ART_CURVETO ? "curveto" :
+ bez[bez_index].code == ART_LINETO ? "lineto" :
+ bez[bez_index].code == ART_MOVETO ? "moveto" :
+ bez[bez_index].code == ART_MOVETO_OPEN ? "moveto-open" :
+ "end", bez[bez_index].x3, bez[bez_index].y3);
+#endif
+ /* make sure space for at least one more code */
+ if (vec_n >= vec_n_max)
+ art_expand (vec, ArtVpath, vec_n_max);
+ switch (bez[bez_index].code)
+ {
+ case ART_MOVETO_OPEN:
+ case ART_MOVETO:
+ case ART_LINETO:
+ x = bez[bez_index].x3;
+ y = bez[bez_index].y3;
+ vec[vec_n].code = bez[bez_index].code;
+ vec[vec_n].x = x;
+ vec[vec_n].y = y;
+ vec_n++;
+ break;
+ case ART_END:
+ vec[vec_n].code = bez[bez_index].code;
+ vec[vec_n].x = 0;
+ vec[vec_n].y = 0;
+ vec_n++;
+ break;
+ case ART_CURVETO:
+#ifdef VERBOSE
+ printf ("%g,%g %g,%g %g,%g %g,%g\n", x, y,
+ bez[bez_index].x1, bez[bez_index].y1,
+ bez[bez_index].x2, bez[bez_index].y2,
+ bez[bez_index].x3, bez[bez_index].y3);
+#endif
+ art_vpath_render_bez (&vec, &vec_n, &vec_n_max,
+ x, y,
+ bez[bez_index].x1, bez[bez_index].y1,
+ bez[bez_index].x2, bez[bez_index].y2,
+ bez[bez_index].x3, bez[bez_index].y3,
+ flatness);
+ x = bez[bez_index].x3;
+ y = bez[bez_index].y3;
+ break;
+ }
+ }
+ while (bez[bez_index++].code != ART_END);
+ return vec;
+}
+
diff -Nru swftools-0.9.2+ds1/lib/art/art_vpath_bpath.h swftools-0.9.1/lib/art/art_vpath_bpath.h
--- swftools-0.9.2+ds1/lib/art/art_vpath_bpath.h 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/art/art_vpath_bpath.h 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,48 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __ART_VPATH_BPATH_H__
+#define __ART_VPATH_BPATH_H__
+
+#ifdef LIBART_COMPILATION
+#include "art_bpath.h"
+#include "art_vpath.h"
+#else
+#include "art_bpath.h"
+#include "art_vpath.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+ArtPoint *art_bezier_to_vec (double x0, double y0,
+ double x1, double y1,
+ double x2, double y2,
+ double x3, double y3,
+ ArtPoint *p,
+ int level);
+
+ArtVpath *art_bez_path_to_vec (const ArtBpath *bez, double flatness);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __ART_VPATH_BPATH_H__ */
diff -Nru swftools-0.9.2+ds1/lib/art/art_vpath.c swftools-0.9.1/lib/art/art_vpath.c
--- swftools-0.9.2+ds1/lib/art/art_vpath.c 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/art/art_vpath.c 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,241 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998-2000 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/* Basic constructors and operations for vector paths */
+
+#include "config.h"
+#include "art_vpath.h"
+
+#include
+#include
+
+#include "art_misc.h"
+
+#include "art_rect.h"
+
+/**
+ * art_vpath_add_point: Add point to vpath.
+ * @p_vpath: Where the pointer to the #ArtVpath structure is stored.
+ * @pn_points: Pointer to the number of points in *@p_vpath.
+ * @pn_points_max: Pointer to the number of points allocated.
+ * @code: The pathcode for the new point.
+ * @x: The X coordinate of the new point.
+ * @y: The Y coordinate of the new point.
+ *
+ * Adds a new point to *@p_vpath, reallocating and updating *@p_vpath
+ * and *@pn_points_max as necessary. *@pn_points is incremented.
+ *
+ * This routine always adds the point after all points already in the
+ * vpath. Thus, it should be called in the order the points are
+ * desired.
+ **/
+void
+art_vpath_add_point (ArtVpath **p_vpath, int *pn_points, int *pn_points_max,
+ ArtPathcode code, double x, double y)
+{
+ int i;
+
+ i = (*pn_points)++;
+ if (i == *pn_points_max)
+ art_expand (*p_vpath, ArtVpath, *pn_points_max);
+ (*p_vpath)[i].code = code;
+ (*p_vpath)[i].x = x;
+ (*p_vpath)[i].y = y;
+}
+
+/* number of steps should really depend on radius. */
+#define CIRCLE_STEPS 128
+
+/**
+ * art_vpath_new_circle: Create a new circle.
+ * @x: X coordinate of center.
+ * @y: Y coordinate of center.
+ * @r: radius.
+ *
+ * Creates a new polygon closely approximating a circle with center
+ * (@x, @y) and radius @r. Currently, the number of points used in the
+ * approximation is fixed, but that will probably change.
+ *
+ * Return value: The newly created #ArtVpath.
+ **/
+ArtVpath *
+art_vpath_new_circle (double x, double y, double r)
+{
+ int i;
+ ArtVpath *vec;
+ double theta;
+
+ vec = (ArtVpath*)art_new (ArtVpath, CIRCLE_STEPS + 2);
+
+ for (i = 0; i < CIRCLE_STEPS + 1; i++)
+ {
+ vec[i].code = i ? ART_LINETO : ART_MOVETO;
+ theta = (i & (CIRCLE_STEPS - 1)) * (M_PI * 2.0 / CIRCLE_STEPS);
+ vec[i].x = x + r * cos (theta);
+ vec[i].y = y - r * sin (theta);
+ }
+ vec[i].code = ART_END;
+
+ return vec;
+}
+
+/**
+ * art_vpath_affine_transform: Affine transform a vpath.
+ * @src: Source vpath to transform.
+ * @matrix: Affine transform.
+ *
+ * Computes the affine transform of the vpath, using @matrix as the
+ * transform. @matrix is stored in the same format as PostScript, ie.
+ * x' = @matrix[0] * x + @matrix[2] * y + @matrix[4]
+ * y' = @matrix[1] * x + @matrix[3] * y + @matrix[5]
+ *
+ * Return value: the newly allocated vpath resulting from the transform.
+**/
+ArtVpath *
+art_vpath_affine_transform (const ArtVpath *src, const double matrix[6])
+{
+ int i;
+ int size;
+ ArtVpath *xnew;
+ double x, y;
+
+ for (i = 0; src[i].code != ART_END; i++);
+ size = i;
+
+ xnew = (ArtVpath*)art_new (ArtVpath, size + 1);
+
+ for (i = 0; i < size; i++)
+ {
+ xnew[i].code = src[i].code;
+ x = src[i].x;
+ y = src[i].y;
+ xnew[i].x = matrix[0] * x + matrix[2] * y + matrix[4];
+ xnew[i].y = matrix[1] * x + matrix[3] * y + matrix[5];
+ }
+ xnew[i].code = ART_END;
+
+ return xnew;
+}
+
+/**
+ * art_vpath_bbox_drect: Determine bounding box of vpath.
+ * @vec: Source vpath.
+ * @drect: Where to store bounding box.
+ *
+ * Determines bounding box of @vec, and stores it in @drect.
+ **/
+void
+art_vpath_bbox_drect (const ArtVpath *vec, ArtDRect *drect)
+{
+ int i;
+ double x0, y0, x1, y1;
+
+ if (vec[0].code == ART_END)
+ {
+ x0 = y0 = x1 = y1 = 0;
+ }
+ else
+ {
+ x0 = x1 = vec[0].x;
+ y0 = y1 = vec[0].y;
+ for (i = 1; vec[i].code != ART_END; i++)
+ {
+ if (vec[i].x < x0) x0 = vec[i].x;
+ if (vec[i].x > x1) x1 = vec[i].x;
+ if (vec[i].y < y0) y0 = vec[i].y;
+ if (vec[i].y > y1) y1 = vec[i].y;
+ }
+ }
+ drect->x0 = x0;
+ drect->y0 = y0;
+ drect->x1 = x1;
+ drect->y1 = y1;
+}
+
+/**
+ * art_vpath_bbox_irect: Determine integer bounding box of vpath.
+ * @vec: Source vpath.
+ * idrect: Where to store bounding box.
+ *
+ * Determines integer bounding box of @vec, and stores it in @irect.
+ **/
+void
+art_vpath_bbox_irect (const ArtVpath *vec, ArtIRect *irect)
+{
+ ArtDRect drect;
+
+ art_vpath_bbox_drect (vec, &drect);
+ art_drect_to_irect (irect, &drect);
+}
+
+#define PERTURBATION 2e-3
+
+/**
+ * art_vpath_perturb: Perturb each point in vpath by small random amount.
+ * @src: Source vpath.
+ *
+ * Perturbs each of the points by a small random amount. This is
+ * helpful for cheating in cases when algorithms haven't attained
+ * numerical stability yet.
+ *
+ * Return value: Newly allocated vpath containing perturbed @src.
+ **/
+ArtVpath *
+art_vpath_perturb (ArtVpath *src)
+{
+ int i;
+ int size;
+ ArtVpath *xnew;
+ double x, y;
+ double x_start, y_start;
+ int open;
+
+ for (i = 0; src[i].code != ART_END; i++);
+ size = i;
+
+ xnew = (ArtVpath*)art_new (ArtVpath, size + 1);
+
+ x_start = 0;
+ y_start = 0;
+ open = 0;
+ for (i = 0; i < size; i++)
+ {
+ xnew[i].code = src[i].code;
+ x = src[i].x + (PERTURBATION * rand ()) / RAND_MAX - PERTURBATION * 0.5;
+ y = src[i].y + (PERTURBATION * rand ()) / RAND_MAX - PERTURBATION * 0.5;
+ if (src[i].code == ART_MOVETO)
+ {
+ x_start = x;
+ y_start = y;
+ open = 0;
+ }
+ else if (src[i].code == ART_MOVETO_OPEN)
+ open = 1;
+ if (!open && (i + 1 == size || src[i + 1].code != ART_LINETO))
+ {
+ x = x_start;
+ y = y_start;
+ }
+ xnew[i].x = x;
+ xnew[i].y = y;
+ }
+ xnew[i].code = ART_END;
+
+ return xnew;
+}
diff -Nru swftools-0.9.2+ds1/lib/art/art_vpath_dash.c swftools-0.9.1/lib/art/art_vpath_dash.c
--- swftools-0.9.2+ds1/lib/art/art_vpath_dash.c 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/art/art_vpath_dash.c 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,200 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1999-2000 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/* Apply a dash style to a vector path. */
+
+#include "config.h"
+#include "art_vpath_dash.h"
+
+#include
+#include
+
+#include "art_misc.h"
+
+#include "art_vpath.h"
+
+
+/* Return the length of the largest subpath within vpath */
+static int
+art_vpath_dash_max_subpath (const ArtVpath *vpath)
+{
+ int max_subpath;
+ int i;
+ int start;
+
+ max_subpath = 0;
+ start = 0;
+ for (i = 0; vpath[i].code != ART_END; i++)
+ {
+ if (vpath[i].code == ART_MOVETO || vpath[i].code == ART_MOVETO_OPEN)
+ {
+ if (i - start > max_subpath)
+ max_subpath = i - start;
+ start = i;
+ }
+ }
+ if (i - start > max_subpath)
+ max_subpath = i - start;
+
+ return max_subpath;
+}
+
+/**
+ * art_vpath_dash: Add dash style to vpath.
+ * @vpath: Original vpath.
+ * @dash: Dash style.
+ *
+ * Creates a new vpath that is the result of applying dash style @dash
+ * to @vpath.
+ *
+ * This implementation has two known flaws:
+ *
+ * First, it adds a spurious break at the beginning of the vpath. The
+ * only way I see to resolve this flaw is to run the state forward one
+ * dash break at the beginning, and fix up by looping back to the
+ * first dash break at the end. This is doable but of course adds some
+ * complexity.
+ *
+ * Second, it does not suppress output points that are within epsilon
+ * of each other.
+ *
+ * Return value: Newly created vpath.
+ **/
+ArtVpath *
+art_vpath_dash (const ArtVpath *vpath, const ArtVpathDash *dash)
+{
+ int max_subpath;
+ double *dists;
+ ArtVpath *result;
+ int n_result, n_result_max;
+ int start, end;
+ int i;
+ double total_dist;
+
+ /* state while traversing dasharray - offset is offset of current dash
+ value, toggle is 0 for "off" and 1 for "on", and phase is the distance
+ in, >= 0, < dash->dash[offset]. */
+ int offset, toggle;
+ double phase;
+
+ /* initial values */
+ int offset_init, toggle_init;
+ double phase_init;
+
+ max_subpath = art_vpath_dash_max_subpath (vpath);
+ dists = art_new (double, max_subpath);
+
+ n_result = 0;
+ n_result_max = 16;
+ result = art_new (ArtVpath, n_result_max);
+
+ /* determine initial values of dash state */
+ toggle_init = 1;
+ offset_init = 0;
+ phase_init = dash->offset;
+ while (phase_init >= dash->dash[offset_init])
+ {
+ toggle_init = !toggle_init;
+ phase_init -= dash->dash[offset_init];
+ offset_init++;
+ if (offset_init == dash->n_dash)
+ offset_init = 0;
+ }
+
+ for (start = 0; vpath[start].code != ART_END; start = end)
+ {
+ for (end = start + 1; vpath[end].code == ART_LINETO; end++);
+ /* subpath is [start..end) */
+ total_dist = 0;
+ for (i = start; i < end - 1; i++)
+ {
+ double dx, dy;
+
+ dx = vpath[i + 1].x - vpath[i].x;
+ dy = vpath[i + 1].y - vpath[i].y;
+ dists[i - start] = sqrt (dx * dx + dy * dy);
+ total_dist += dists[i - start];
+ }
+ if (total_dist <= dash->dash[offset_init] - phase_init)
+ {
+ /* subpath fits entirely within first dash */
+ if (toggle_init)
+ {
+ for (i = start; i < end; i++)
+ art_vpath_add_point (&result, &n_result, &n_result_max,
+ vpath[i].code, vpath[i].x, vpath[i].y);
+ }
+ }
+ else
+ {
+ /* subpath is composed of at least one dash - thus all
+ generated pieces are open */
+ double dist;
+
+ phase = phase_init;
+ offset = offset_init;
+ toggle = toggle_init;
+ dist = 0;
+ i = start;
+ if (toggle)
+ art_vpath_add_point (&result, &n_result, &n_result_max,
+ ART_MOVETO_OPEN, vpath[i].x, vpath[i].y);
+ while (i != end - 1)
+ {
+ if (dists[i - start] - dist > dash->dash[offset] - phase)
+ {
+ /* dash boundary is next */
+ double a;
+ double x, y;
+
+ dist += dash->dash[offset] - phase;
+ a = dist / dists[i - start];
+ x = vpath[i].x + a * (vpath[i + 1].x - vpath[i].x);
+ y = vpath[i].y + a * (vpath[i + 1].y - vpath[i].y);
+ art_vpath_add_point (&result, &n_result, &n_result_max,
+ toggle ? ART_LINETO : ART_MOVETO_OPEN,
+ x, y);
+ /* advance to next dash */
+ toggle = !toggle;
+ phase = 0;
+ offset++;
+ if (offset == dash->n_dash)
+ offset = 0;
+ }
+ else
+ {
+ /* end of line in vpath is next */
+ phase += dists[i - start] - dist;
+ i++;
+ dist = 0;
+ if (toggle)
+ art_vpath_add_point (&result, &n_result, &n_result_max,
+ ART_LINETO, vpath[i].x, vpath[i].y);
+ }
+ }
+ }
+ }
+
+ art_vpath_add_point (&result, &n_result, &n_result_max,
+ ART_END, 0, 0);
+
+ art_free (dists);
+
+ return result;
+}
diff -Nru swftools-0.9.2+ds1/lib/art/art_vpath_dash.h swftools-0.9.1/lib/art/art_vpath_dash.h
--- swftools-0.9.2+ds1/lib/art/art_vpath_dash.h 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/art/art_vpath_dash.h 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,50 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1999 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __ART_VPATH_DASH_H__
+#define __ART_VPATH_DASH_H__
+
+/* Apply a dash style to a vector path. */
+
+#ifdef LIBART_COMPILATION
+#include "art_vpath.h"
+#else
+#include "art_vpath.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+typedef struct _ArtVpathDash ArtVpathDash;
+
+struct _ArtVpathDash {
+ double offset;
+ int n_dash;
+ double *dash;
+};
+
+ArtVpath *
+art_vpath_dash (const ArtVpath *vpath, const ArtVpathDash *dash);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __ART_VPATH_DASH_H__ */
diff -Nru swftools-0.9.2+ds1/lib/art/art_vpath.h swftools-0.9.1/lib/art/art_vpath.h
--- swftools-0.9.2+ds1/lib/art/art_vpath.h 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/art/art_vpath.h 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,71 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __ART_VPATH_H__
+#define __ART_VPATH_H__
+
+#ifdef LIBART_COMPILATION
+#include "art_rect.h"
+#include "art_pathcode.h"
+#else
+#include "art_rect.h"
+#include "art_pathcode.h"
+#endif
+
+/* Basic data structures and constructors for simple vector paths */
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+typedef struct _ArtVpath ArtVpath;
+
+/* CURVETO is not allowed! */
+struct _ArtVpath {
+ ArtPathcode code;
+ double x;
+ double y;
+};
+
+/* Some of the functions need to go into their own modules */
+
+void
+art_vpath_add_point (ArtVpath **p_vpath, int *pn_points, int *pn_points_max,
+ ArtPathcode code, double x, double y);
+
+ArtVpath *
+art_vpath_new_circle (double x, double y, double r);
+
+ArtVpath *
+art_vpath_affine_transform (const ArtVpath *src, const double matrix[6]);
+
+void
+art_vpath_bbox_drect (const ArtVpath *vec, ArtDRect *drect);
+
+void
+art_vpath_bbox_irect (const ArtVpath *vec, ArtIRect *irect);
+
+ArtVpath *
+art_vpath_perturb (ArtVpath *src);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __ART_VPATH_H__ */
diff -Nru swftools-0.9.2+ds1/lib/art/art_vpath_svp.c swftools-0.9.1/lib/art/art_vpath_svp.c
--- swftools-0.9.2+ds1/lib/art/art_vpath_svp.c 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/art/art_vpath_svp.c 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,196 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998-2000 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/* "Unsort" a sorted vector path into an ordinary vector path. */
+
+#include "config.h"
+#include "art_vpath_svp.h"
+
+#include /* for printf - debugging */
+#include "art_misc.h"
+
+#include "art_vpath.h"
+#include "art_svp.h"
+
+typedef struct _ArtVpathSVPEnd ArtVpathSVPEnd;
+
+struct _ArtVpathSVPEnd {
+ int seg_num;
+ int which; /* 0 = top, 1 = bottom */
+ double x, y;
+};
+
+#define EPSILON 1e-6
+
+static int
+art_vpath_svp_point_compare (double x1, double y1, double x2, double y2)
+{
+ if (y1 - EPSILON > y2) return 1;
+ if (y1 + EPSILON < y2) return -1;
+ if (x1 - EPSILON > x2) return 1;
+ if (x1 + EPSILON < x2) return -1;
+ return 0;
+}
+
+static int
+art_vpath_svp_compare (const void *s1, const void *s2)
+{
+ const ArtVpathSVPEnd *e1 = (ArtVpathSVPEnd *)s1;
+ const ArtVpathSVPEnd *e2 = (ArtVpathSVPEnd *)s2;
+
+ return art_vpath_svp_point_compare (e1->x, e1->y, e2->x, e2->y);
+}
+
+/* Convert from sorted vector path representation into regular
+ vector path representation.
+
+ Status of this routine:
+
+ Basic correctness: Only works with closed paths.
+
+ Numerical stability: Not known to work when more than two segments
+ meet at a point.
+
+ Speed: Should be pretty good.
+
+ Precision: Does not degrade precision.
+
+*/
+/**
+ * art_vpath_from_svp: Convert from svp to vpath form.
+ * @svp: Original #ArtSVP.
+ *
+ * Converts the sorted vector path @svp into standard vpath form.
+ *
+ * Return value: the newly allocated vpath.
+ **/
+ArtVpath *
+art_vpath_from_svp (const ArtSVP *svp)
+{
+ int n_segs = svp->n_segs;
+ ArtVpathSVPEnd *ends;
+ ArtVpath *xnew;
+ int *visited;
+ int n_new, n_new_max;
+ int i, k;
+ int j = 0; /* Quiet compiler */
+ int seg_num;
+ int first;
+ double last_x, last_y;
+ int n_points;
+ int pt_num;
+
+ last_x = 0; /* to eliminate "uninitialized" warning */
+ last_y = 0;
+
+ ends = (ArtVpathSVPEnd*)art_new (ArtVpathSVPEnd, n_segs * 2);
+ for (i = 0; i < svp->n_segs; i++)
+ {
+ int lastpt;
+
+ ends[i * 2].seg_num = i;
+ ends[i * 2].which = 0;
+ ends[i * 2].x = svp->segs[i].points[0].x;
+ ends[i * 2].y = svp->segs[i].points[0].y;
+
+ lastpt = svp->segs[i].n_points - 1;
+ ends[i * 2 + 1].seg_num = i;
+ ends[i * 2 + 1].which = 1;
+ ends[i * 2 + 1].x = svp->segs[i].points[lastpt].x;
+ ends[i * 2 + 1].y = svp->segs[i].points[lastpt].y;
+ }
+ qsort (ends, n_segs * 2, sizeof (ArtVpathSVPEnd), art_vpath_svp_compare);
+
+ n_new = 0;
+ n_new_max = 16; /* I suppose we _could_ estimate this from traversing
+ the svp, so we don't have to reallocate */
+ xnew = (ArtVpath*)art_new (ArtVpath, n_new_max);
+
+ visited = (int*)art_new (int, n_segs);
+ for (i = 0; i < n_segs; i++)
+ visited[i] = 0;
+
+ first = 1;
+ for (i = 0; i < n_segs; i++)
+ {
+ if (!first)
+ {
+ /* search for the continuation of the existing subpath */
+ /* This could be a binary search (which is why we sorted, above) */
+ for (j = 0; j < n_segs * 2; j++)
+ {
+ if (!visited[ends[j].seg_num] &&
+ art_vpath_svp_point_compare (last_x, last_y,
+ ends[j].x, ends[j].y) == 0)
+ break;
+ }
+ if (j == n_segs * 2)
+ first = 1;
+ }
+ if (first)
+ {
+ /* start a new subpath */
+ for (j = 0; j < n_segs * 2; j++)
+ if (!visited[ends[j].seg_num])
+ break;
+ }
+ if (j == n_segs * 2)
+ {
+ printf ("failure\n");
+ }
+ seg_num = ends[j].seg_num;
+ n_points = svp->segs[seg_num].n_points;
+ for (k = 0; k < n_points; k++)
+ {
+ pt_num = svp->segs[seg_num].dir ? k : n_points - (1 + k);
+ if (k == 0)
+ {
+ if (first)
+ {
+ art_vpath_add_point (&xnew, &n_new, &n_new_max,
+ ART_MOVETO,
+ svp->segs[seg_num].points[pt_num].x,
+ svp->segs[seg_num].points[pt_num].y);
+ }
+ }
+ else
+ {
+ art_vpath_add_point (&xnew, &n_new, &n_new_max,
+ ART_LINETO,
+ svp->segs[seg_num].points[pt_num].x,
+ svp->segs[seg_num].points[pt_num].y);
+ if (k == n_points - 1)
+ {
+ last_x = svp->segs[seg_num].points[pt_num].x;
+ last_y = svp->segs[seg_num].points[pt_num].y;
+ /* to make more robust, check for meeting first_[xy],
+ set first if so */
+ }
+ }
+ first = 0;
+ }
+ visited[seg_num] = 1;
+ }
+
+ art_vpath_add_point (&xnew, &n_new, &n_new_max,
+ ART_END, 0, 0);
+ art_free (visited);
+ art_free (ends);
+ return xnew;
+}
diff -Nru swftools-0.9.2+ds1/lib/art/art_vpath_svp.h swftools-0.9.1/lib/art/art_vpath_svp.h
--- swftools-0.9.2+ds1/lib/art/art_vpath_svp.h 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/art/art_vpath_svp.h 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,43 @@
+/* Libart_LGPL - library of basic graphic primitives
+ * Copyright (C) 1998 Raph Levien
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __ART_VPATH_SVP_H__
+#define __ART_VPATH_SVP_H__
+
+/* "Unsort" a sorted vector path into an ordinary vector path. */
+
+#ifdef LIBART_COMPILATION
+#include "art_svp.h"
+#include "art_vpath.h"
+#else
+#include "art_svp.h"
+#include "art_vpath.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+ArtVpath *art_vpath_from_svp (const ArtSVP *svp);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __ART_VPATH_SVP_H__ */
diff -Nru swftools-0.9.2+ds1/lib/art/config.h swftools-0.9.1/lib/art/config.h
--- swftools-0.9.2+ds1/lib/art/config.h 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/art/config.h 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,3 @@
+/* Define to 1 if your processor stores words with the most significant byte
+ first (like Motorola and SPARC, unlike Intel and VAX). */
+/* #undef WORDS_BIGENDIAN */
diff -Nru swftools-0.9.2+ds1/lib/art/gen_art_config.c swftools-0.9.1/lib/art/gen_art_config.c
--- swftools-0.9.2+ds1/lib/art/gen_art_config.c 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/art/gen_art_config.c 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,52 @@
+#include
+#include "config.h"
+#include
+
+/**
+ * A little utility function to generate header info.
+ *
+ * Yes, it would be possible to do this using more "native" autoconf
+ * features, but I personally find this approach to be cleaner.
+ *
+ * The output of this program is generally written to art_config.h,
+ * which is installed in libart's include dir.
+ **/
+
+static void
+die (char *why)
+{
+ fprintf (stderr, "gen_art_config: %s\n", why);
+ exit (1);
+}
+
+int
+main (int argc, char **argv)
+{
+ printf ("/* Automatically generated by gen_art_config.c */\n"
+ "\n"
+ "#define ART_SIZEOF_CHAR %d\n"
+ "#define ART_SIZEOF_SHORT %d\n"
+ "#define ART_SIZEOF_INT %d\n"
+ "#define ART_SIZEOF_LONG %d\n"
+ "\n",
+ (int)sizeof(char), (int)sizeof(short), (int)sizeof(int), (int)sizeof(long));
+
+ if (sizeof(char) == 1)
+ printf ("typedef unsigned char art_u8;\n");
+ else
+ die ("sizeof(char) != 1");
+
+ if (sizeof(short) == 2)
+ printf ("typedef unsigned short art_u16;\n");
+ else
+ die ("sizeof(short) != 2");
+
+ if (sizeof(int) == 4)
+ printf ("typedef unsigned int art_u32;\n");
+ else if (sizeof(long) == 4)
+ printf ("typedef unsigned long art_u32;\n");
+ else
+ die ("sizeof(int) != 4 and sizeof(long) != 4");
+
+ return 0;
+}
diff -Nru swftools-0.9.2+ds1/lib/art/libart.h swftools-0.9.1/lib/art/libart.h
--- swftools-0.9.2+ds1/lib/art/libart.h 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/art/libart.h 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,39 @@
+#ifndef LIBART_H
+#define LIBART_H 1
+
+#include "art_affine.h"
+#include "art_alphagamma.h"
+#include "art_bpath.h"
+#include "art_filterlevel.h"
+#include "art_gray_svp.h"
+#include "art_misc.h"
+#include "art_pathcode.h"
+#include "art_pixbuf.h"
+#include "art_point.h"
+#include "art_rect.h"
+#include "art_rect_svp.h"
+#include "art_rect_uta.h"
+#include "art_rgb.h"
+#include "art_rgb_affine.h"
+#include "art_rgb_bitmap_affine.h"
+#include "art_rgb_pixbuf_affine.h"
+#include "art_rgb_rgba_affine.h"
+#include "art_rgb_svp.h"
+#include "art_svp.h"
+#include "art_svp_ops.h"
+#include "art_svp_point.h"
+#include "art_svp_render_aa.h"
+#include "art_svp_vpath.h"
+#include "art_svp_vpath_stroke.h"
+#include "art_svp_wind.h"
+#include "art_uta.h"
+#include "art_uta_ops.h"
+#include "art_uta_rect.h"
+#include "art_uta_svp.h"
+#include "art_uta_vpath.h"
+#include "art_vpath.h"
+#include "art_vpath_bpath.h"
+#include "art_vpath_dash.h"
+#include "art_vpath_svp.h"
+
+#endif
diff -Nru swftools-0.9.2+ds1/lib/art/Makefile.in swftools-0.9.1/lib/art/Makefile.in
--- swftools-0.9.2+ds1/lib/art/Makefile.in 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/art/Makefile.in 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,22 @@
+top_builddir = ../..
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+include ../../Makefile.common
+
+libart_objects = art_affine.$(O) art_alphagamma.$(O) art_bpath.$(O) art_gray_svp.$(O) art_misc.$(O) art_pixbuf.$(O) art_rect.$(O) art_rect_svp.$(O) art_rect_uta.$(O) art_render.$(O) art_render_gradient.$(O) art_render_mask.$(O) art_render_svp.$(O) art_rgb.$(O) art_rgb_a_affine.$(O) art_rgb_affine.$(O) art_rgb_affine_private.$(O) art_rgb_bitmap_affine.$(O) art_rgb_pixbuf_affine.$(O) art_rgb_rgba_affine.$(O) art_rgb_svp.$(O) art_rgba.$(O) art_svp.$(O) art_svp_intersect.$(O) art_svp_ops.$(O) art_svp_point.$(O) art_svp_render_aa.$(O) art_svp_vpath.$(O) art_svp_vpath_stroke.$(O) art_svp_wind.$(O) art_uta.$(O) art_uta_ops.$(O) art_uta_rect.$(O) art_uta_svp.$(O) art_uta_vpath.$(O) art_vpath.$(O) art_vpath_bpath.$(O) art_vpath_dash.$(O) art_vpath_svp.$(O)
+
+all: libart$(A)
+
+libart$(A): $(libart_objects)
+ $(AR) r libart$(A) $(libart_objects)
+ $(RANLIB) libart$(A)
+
+%.$(O): %.c
+ $(C) $< -o $@
+
+install:
+uninstall:
+clean:
+ rm -f *.o *.obj *.lo *.a *.lib *.la gmon.out
+
+
diff -Nru swftools-0.9.2+ds1/lib/as3/err/badbreak.as swftools-0.9.1/lib/as3/err/badbreak.as
--- swftools-0.9.2+ds1/lib/as3/err/badbreak.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/err/badbreak.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,18 @@
+package {
+ import flash.display.MovieClip
+ public class Main extends flash.display.MovieClip {
+ function Main() {
+ var i:int;
+
+ /* test for loop */
+ var j:int=0;
+ for(i=0;i<100;i++) {
+ j++;
+ if(i!=50)
+ break badname;
+ trace("ok 1/6");
+ }
+ }
+ }
+}
+
diff -Nru swftools-0.9.2+ds1/lib/as3/err/badcontinue.as swftools-0.9.1/lib/as3/err/badcontinue.as
--- swftools-0.9.2+ds1/lib/as3/err/badcontinue.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/err/badcontinue.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,18 @@
+package {
+ import flash.display.MovieClip
+ public class Main extends flash.display.MovieClip {
+ function Main() {
+ var i:int;
+
+ /* test for loop */
+ var j:int=0;
+ for(i=0;i<100;i++) {
+ j++;
+ if(i!=50)
+ continue badname;
+ trace("ok 1/6");
+ }
+ }
+ }
+}
+
diff -Nru swftools-0.9.2+ds1/lib/as3/err/bogusimport.as swftools-0.9.1/lib/as3/err/bogusimport.as
--- swftools-0.9.2+ds1/lib/as3/err/bogusimport.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/err/bogusimport.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,3 @@
+package abc {
+ import some.nonexisting.package.MyClass;
+}
diff -Nru swftools-0.9.2+ds1/lib/as3/err/callpackageinternal.as swftools-0.9.1/lib/as3/err/callpackageinternal.as
--- swftools-0.9.2+ds1/lib/as3/err/callpackageinternal.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/err/callpackageinternal.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,10 @@
+package some.other.module {
+ function getmsg() {
+ trace("error");
+ }
+}
+
+package {
+ import some.other.module.*;
+ getmsg();
+}
diff -Nru swftools-0.9.2+ds1/lib/as3/err/defaultargmismatch.as swftools-0.9.1/lib/as3/err/defaultargmismatch.as
--- swftools-0.9.2+ds1/lib/as3/err/defaultargmismatch.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/err/defaultargmismatch.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,8 @@
+package I {
+ public class A {
+ public function f(x) {}
+ }
+ public class B extends A {
+ override public function f(x=4) {}
+ }
+}
diff -Nru swftools-0.9.2+ds1/lib/as3/err/doubleclass.as swftools-0.9.1/lib/as3/err/doubleclass.as
--- swftools-0.9.2+ds1/lib/as3/err/doubleclass.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/err/doubleclass.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,12 @@
+package abc {
+ class Twice {
+ }
+}
+package def {
+ class Twice {
+ }
+}
+package abc {
+ class Twice {
+ }
+}
diff -Nru swftools-0.9.2+ds1/lib/as3/err/double_namespace.as swftools-0.9.1/lib/as3/err/double_namespace.as
--- swftools-0.9.2+ds1/lib/as3/err/double_namespace.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/err/double_namespace.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,10 @@
+package my.namespaces {
+ public namespace ns1 = "http://www.some.other/namespace";
+ public namespace ns2 = "http://www.swftools.org/";
+
+ public class Test {
+ ns1 ns2 static function test() {
+ }
+ }
+}
+
diff -Nru swftools-0.9.2+ds1/lib/as3/err/final2.as swftools-0.9.1/lib/as3/err/final2.as
--- swftools-0.9.2+ds1/lib/as3/err/final2.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/err/final2.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,13 @@
+package {
+ class A {
+ final public function f() {
+ }
+ }
+
+ public class Main extends A
+ {
+ //error: f is final:
+ override public function f() {
+ }
+ }
+}
diff -Nru swftools-0.9.2+ds1/lib/as3/err/final.as swftools-0.9.1/lib/as3/err/final.as
--- swftools-0.9.2+ds1/lib/as3/err/final.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/err/final.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,11 @@
+package {
+ final class A {
+ function A() {
+ }
+ }
+
+ //error: A is final:
+ public class Main extends A
+ {
+ }
+}
diff -Nru swftools-0.9.2+ds1/lib/as3/err/innerfunctionassign.as swftools-0.9.1/lib/as3/err/innerfunctionassign.as
--- swftools-0.9.2+ds1/lib/as3/err/innerfunctionassign.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/err/innerfunctionassign.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,22 @@
+package {
+ import flash.display.MovieClip
+ import flash.events.Event
+
+ public class Main extends flash.display.MovieClip {
+
+ /* this test is just to showcase a problem with slotted functions
+ in conjunction with inner function assignment.
+ What (I think) the compiler should do is just to prevent inner
+ functions from being assigned. */
+ public function Main() {
+ function f0() {
+ trace("error");
+ }
+ f0 = function(s:String) {
+ trace(s);
+ }
+ f0("ok 1/2");
+ function() {f0("ok 2/2");}()
+ }
+ }
+}
diff -Nru swftools-0.9.2+ds1/lib/as3/err/interface2.as swftools-0.9.1/lib/as3/err/interface2.as
--- swftools-0.9.2+ds1/lib/as3/err/interface2.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/err/interface2.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,7 @@
+package I {
+ public interface I1 {
+ function f() {
+ trace("..."); // method body not allowed
+ }
+ }
+}
diff -Nru swftools-0.9.2+ds1/lib/as3/err/interface3.as swftools-0.9.1/lib/as3/err/interface3.as
--- swftools-0.9.2+ds1/lib/as3/err/interface3.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/err/interface3.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,5 @@
+package I {
+ public interface I1 {
+ var x; // variable declaration not allowed
+ }
+}
diff -Nru swftools-0.9.2+ds1/lib/as3/err/interface4.as swftools-0.9.1/lib/as3/err/interface4.as
--- swftools-0.9.2+ds1/lib/as3/err/interface4.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/err/interface4.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,9 @@
+package I {
+ class D {
+ }
+
+ //error: can only implement interfaces, not classes
+ class C implements D
+ {
+ }
+}
diff -Nru swftools-0.9.2+ds1/lib/as3/err/interface5.as swftools-0.9.1/lib/as3/err/interface5.as
--- swftools-0.9.2+ds1/lib/as3/err/interface5.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/err/interface5.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,14 @@
+package {
+ interface A {
+ function f()
+ }
+ interface B {
+ function f(x)
+ }
+
+ public class C implements A,B
+ {
+ // ambigious definition (or: B.f not implemented)
+ public function f() {}
+ }
+}
diff -Nru swftools-0.9.2+ds1/lib/as3/err/interface6.as swftools-0.9.1/lib/as3/err/interface6.as
--- swftools-0.9.2+ds1/lib/as3/err/interface6.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/err/interface6.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,10 @@
+package {
+ interface A {
+ var x;
+
+ // error: interface can not have top-level code
+ if(x==0) {
+ } else {
+ }
+ }
+}
diff -Nru swftools-0.9.2+ds1/lib/as3/err/interface.as swftools-0.9.1/lib/as3/err/interface.as
--- swftools-0.9.2+ds1/lib/as3/err/interface.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/err/interface.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,6 @@
+package I {
+ public interface I1 {
+ // access modifiers not allowed
+ private function f()
+ }
+}
diff -Nru swftools-0.9.2+ds1/lib/as3/err/internalvar.as swftools-0.9.1/lib/as3/err/internalvar.as
--- swftools-0.9.2+ds1/lib/as3/err/internalvar.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/err/internalvar.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,14 @@
+package package1 {
+ public class A {
+ internal var x;
+ }
+}
+package package2 {
+
+ public class Test extends flash.display.MovieClip {
+ public function Test() {
+ var cls = new package1.A();
+ cls.x=3; //invalid: x is internal
+ }
+ }
+}
diff -Nru swftools-0.9.2+ds1/lib/as3/err/invalidthis.as swftools-0.9.1/lib/as3/err/invalidthis.as
--- swftools-0.9.2+ds1/lib/as3/err/invalidthis.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/err/invalidthis.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,3 @@
+function test() {
+ this.x = 3;
+}
diff -Nru swftools-0.9.2+ds1/lib/as3/err/invalidthisassign.as swftools-0.9.1/lib/as3/err/invalidthisassign.as
--- swftools-0.9.2+ds1/lib/as3/err/invalidthisassign.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/err/invalidthisassign.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,8 @@
+package {
+ import flash.display.MovieClip
+ public class Main extends flash.display.MovieClip {
+ function Main() {
+ this = 3;
+ }
+ }
+}
diff -Nru swftools-0.9.2+ds1/lib/as3/err/missingoverride.as swftools-0.9.1/lib/as3/err/missingoverride.as
--- swftools-0.9.2+ds1/lib/as3/err/missingoverride.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/err/missingoverride.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,10 @@
+package I {
+ public interface I1 {
+ function f1()
+ function f2()
+ }
+ public class C {
+ function f1() {}
+ //fail to override f2
+ }
+}
diff -Nru swftools-0.9.2+ds1/lib/as3/err/override2.as swftools-0.9.1/lib/as3/err/override2.as
--- swftools-0.9.2+ds1/lib/as3/err/override2.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/err/override2.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,11 @@
+package p {
+ public class C {
+ public function e() {
+ }
+ }
+ public class D extends C {
+ override function f() {
+ // illegal override: no f() in superclass
+ }
+ }
+}
diff -Nru swftools-0.9.2+ds1/lib/as3/err/override.as swftools-0.9.1/lib/as3/err/override.as
--- swftools-0.9.2+ds1/lib/as3/err/override.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/err/override.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,10 @@
+package p {
+ internal class C {
+ protected function e() {
+ }
+ }
+ public class D extends C {
+ protected function e() {
+ }
+ }
+}
diff -Nru swftools-0.9.2+ds1/lib/as3/err/packagesnested.as swftools-0.9.1/lib/as3/err/packagesnested.as
--- swftools-0.9.2+ds1/lib/as3/err/packagesnested.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/err/packagesnested.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,4 @@
+package Test {
+ package Test2 {
+ }
+}
diff -Nru swftools-0.9.2+ds1/lib/as3/err/private.as swftools-0.9.1/lib/as3/err/private.as
--- swftools-0.9.2+ds1/lib/as3/err/private.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/err/private.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,12 @@
+
+package p {
+ internal class C {
+ private function e() {
+ }
+ }
+ public class D extends C {
+ protected function f() {
+ super.e();
+ }
+ }
+}
diff -Nru swftools-0.9.2+ds1/lib/as3/err/privatevar.as swftools-0.9.1/lib/as3/err/privatevar.as
--- swftools-0.9.2+ds1/lib/as3/err/privatevar.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/err/privatevar.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,11 @@
+package package1 {
+ public class A {
+ private var x;
+ }
+ public class Test extends flash.display.MovieClip {
+ public function Test() {
+ var cls = new package1.A();
+ cls.x=3; //invalid: x is private
+ }
+ }
+}
diff -Nru swftools-0.9.2+ds1/lib/as3/err/protectedvar.as swftools-0.9.1/lib/as3/err/protectedvar.as
--- swftools-0.9.2+ds1/lib/as3/err/protectedvar.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/err/protectedvar.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,11 @@
+package package1 {
+ public class A {
+ protected var x;
+ }
+ public class Test extends flash.display.MovieClip {
+ public function Test() {
+ var cls = new package1.A();
+ cls.x=3; //invalid: x is protected
+ }
+ }
+}
diff -Nru swftools-0.9.2+ds1/lib/as3/err/publicinternal.as swftools-0.9.1/lib/as3/err/publicinternal.as
--- swftools-0.9.2+ds1/lib/as3/err/publicinternal.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/err/publicinternal.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,4 @@
+package mypackage {
+ public internal class Test {
+ }
+}
diff -Nru swftools-0.9.2+ds1/lib/as3/err/publicns.as swftools-0.9.1/lib/as3/err/publicns.as
--- swftools-0.9.2+ds1/lib/as3/err/publicns.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/err/publicns.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,9 @@
+package {
+ public namespace ns1 = "http://www.namespace.com/"
+
+ public class Test {
+ public ns1 function name() {
+ // error: either namespace *or* public
+ }
+ }
+}
diff -Nru swftools-0.9.2+ds1/lib/as3/err/publicoutsidepackage.as swftools-0.9.1/lib/as3/err/publicoutsidepackage.as
--- swftools-0.9.2+ds1/lib/as3/err/publicoutsidepackage.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/err/publicoutsidepackage.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,2 @@
+public class Test {
+}
diff -Nru swftools-0.9.2+ds1/lib/as3/err/static1.as swftools-0.9.1/lib/as3/err/static1.as
--- swftools-0.9.2+ds1/lib/as3/err/static1.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/err/static1.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,9 @@
+package package1 {
+ public class A {
+ public var x;
+ public static function f()
+ {
+ x = 3; //error: this member is not static
+ }
+ }
+}
diff -Nru swftools-0.9.2+ds1/lib/as3/err/staticinherit.as swftools-0.9.1/lib/as3/err/staticinherit.as
--- swftools-0.9.2+ds1/lib/as3/err/staticinherit.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/err/staticinherit.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,13 @@
+package package1 {
+ public class A {
+ public static function f()
+ {
+ }
+ }
+ public class B extends A {
+ public function g()
+ {
+ super.f()
+ }
+ }
+}
diff -Nru swftools-0.9.2+ds1/lib/as3/err/super.as swftools-0.9.1/lib/as3/err/super.as
--- swftools-0.9.2+ds1/lib/as3/err/super.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/err/super.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,17 @@
+package {
+ public class A {
+ function A() {
+ }
+ }
+ public class Main {
+ public var x;
+ public function f() {
+ }
+ function Main() {
+ this.x = 3; // error: access to instance variable before super()
+ this.f()
+ super();
+ super(); // error: super called twice
+ }
+ }
+}
diff -Nru swftools-0.9.2+ds1/lib/as3/main.c swftools-0.9.1/lib/as3/main.c
--- swftools-0.9.2+ds1/lib/as3/main.c 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/main.c 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,173 @@
+/* main.c
+
+ Flash ActionScript 3.0 compiler
+
+ Part of the swftools package.
+
+ Copyright (c) 2008 Matthias Kramm
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include
+#include
+#include
+#include
+#include "../rfxswf.h"
+#include "../os.h"
+#include "files.h"
+#include "common.h"
+#include "tokenizer.h"
+#include "parser.tab.h"
+#include "parser.h"
+#include "compiler.h"
+#include "import.h"
+
+void test_lexer(char*filename)
+{
+ char*fullfilename = find_file(filename, 1);
+ enter_file(filename, fullfilename, 0);
+ FILE*fi = fopen(fullfilename, "rb");
+ as3_file_input(fi);
+ while(1) {
+ int token = as3_lex();
+ if(token==T_EOF)
+ break;
+ if(token>=32 && token<256) {
+ printf("'%c'\n", token);
+ } else {
+ printf("%s\n", token2string(token, a3_lval));
+ }
+ }
+}
+
+extern int a3_debug;
+int main(int argn, char*argv[])
+{
+ char*filename = 0;
+ char buf[512];
+
+ if(argn<=1) {
+ fprintf(stderr, "please supply a filename\n");
+ exit(1);
+ }
+ filename=argv[argn-1];
+
+#ifdef BISONDEBUG
+ a3_debug = 1; //if bison was called with -t
+#endif
+ int width=20, height=10;
+
+ as3_add_include_dir(getcwd(buf, 512));
+
+ registry_init();
+
+ int t=0;
+ char*mainclass = 0;
+ for(t=1;tdata, m->len);
+ //memfile_close(m);
+ if(!strcmp(filename, ".")) {
+ as3_parse_directory(".");
+ } else {
+ as3_parse_file(filename);
+ }
+
+ void*code = as3_getcode();
+
+ SWF swf;
+ memset(&swf, 0, sizeof(swf));
+ swf.fileVersion = 9;
+ swf.frameRate = 0x2500;
+ swf.movieSize.xmin = swf.movieSize.ymin = 0;
+ swf.movieSize.xmax = width*20;
+ swf.movieSize.ymax = height*20;
+
+
+ TAG*tag = swf.firstTag = swf_InsertTag(0, ST_SETBACKGROUNDCOLOR);
+ swf_SetU8(tag, 0xff);
+ swf_SetU8(tag, 0xff);
+ swf_SetU8(tag, 0xff);
+
+ tag = as3_getassets(tag);
+
+ tag = swf_InsertTag(tag, ST_DOABC);
+ if(!swf.firstTag && tag) swf.firstTag = tag;
+ swf_WriteABC(tag, code);
+
+ if(!mainclass)
+ mainclass = as3_getglobalclass();
+
+ if(mainclass) {
+ tag = swf_InsertTag(tag, ST_SYMBOLCLASS);
+ swf_SetU16(tag, 1);
+ swf_SetU16(tag, 0);
+ swf_SetString(tag, mainclass);
+ } else {
+ printf("Warning: no global public MovieClip subclass\n");
+ }
+
+ tag = swf_InsertTag(tag, ST_SHOWFRAME);
+ tag = swf_InsertTag(tag, ST_END);
+
+ swf_FreeABC(code);
+
+ int f = open("abc.swf",O_RDWR|O_CREAT|O_TRUNC|O_BINARY,0644);
+ swf_WriteSWF(f,&swf);
+ close(f);
+
+ swf_FreeTags(&swf);
+
+ return 0;
+}
diff -Nru swftools-0.9.2+ds1/lib/as3/Makefile swftools-0.9.1/lib/as3/Makefile
--- swftools-0.9.2+ds1/lib/as3/Makefile 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/Makefile 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,66 @@
+include ../../Makefile.common
+
+all: parser swfdump mklib
+tests: testwrite testrewrite testpaths testreadwrite
+
+D=-g -pg
+
+#BISONDEBUG=yes
+
+MODULES = abc.o opcodes.o code.o parser_help.o state.o pool.o scripts.o expr.o common.o initcode.o
+SOURCES = abc.c abc.h state.c state.h parser_help.c parser_help.h pool.c pool.h files.c files.h code.c code.h registry.c registry.h opcodes.c opcodes.h builtin.c builtin.h compiler.c compiler.h parser.tab.h parser.tab.c tokenizer.yy.c scripts.c import.c import.h expr.c expr.h common.c common.h initcode.c initcode.h assets.c assets.h
+
+tokenizer.yy.c: tokenizer.lex tokenizer.h
+ flex -Pas3_ -8 -B -otokenizer.yy.c tokenizer.lex
+
+ifeq "$(BISONDEBUG)" "yes"
+BISONDEBUGFLAGS=-t
+BISONDEBUGDEFINE=-DBISONDEBUG
+endif
+parser.tab.h parser.tab.c: parser.y parser.h skeleton.m4 Makefile
+ bison $(BISONDEBUGFLAGS) -S ./skeleton.m4 -v --defines -pa3_ parser.y -o parser.tab.c
+
+main.o: main.c parser.tab.h parser.h
+ $(C) $(BISONDEBUGDEFINE) main.c -o main.o
+
+mklib.o: mklib.c parser.tab.h parser.h
+ $(C) mklib.c -o mklib.o
+
+parser: main.o tokenizer.yy.c ../librfxswf.a ../libbase.a parser.tab.h
+ $(L) main.o ../librfxswf.a ../libbase.a -o parser -lz -lzzip
+
+rfxswf_modules=../drawer.o ../rfxswf.o ../modules/*.o ../lame/*.o ../action/*.o $(MODULES)
+mklib: mklib.o $(rfxswf_modules) import.o registry.o tokenizer.yy.o parser.tab.o files.o compiler.o assets.o ../libbase.a
+ $(L) mklib.o $(rfxswf_modules) import.o registry.o tokenizer.yy.o parser.tab.o files.o compiler.o assets.o ../libbase.a -o mklib $(LIBS)
+
+../q.o: ../q.c ../q.h ../mem.h
+ cd ..; make q.o; cd -
+
+../librfxswf.a: ../rfxswf.h ../rfxswf.c $(SOURCES)
+ cd ..; make librfxswf.a
+
+../libbase.a: ../q.c ../q.h ../mem.c ../mem.h
+ cd ..; make libbase.a
+
+swfdump: ../librfxswf.a ../../src/swfdump.c ../libbase.a $(SOURCES) ../q.c ../q.h
+ $(L) -g ../../src/swfdump.c ../librfxswf.a ../libbase.a -o swfdump $(LIBS)
+
+pdf2swf: ../librfxswf.a ../../src/pdf2swf.c ../libpdf.a ../libbase.a
+ $(LL) -g ../../src/pdf2swf.c ../libgfxswf.a ../libpdf.a ../libgfx.a ../librfxswf.a ../libbase.a -o pdf2swf $(LIBS)
+
+testreadwrite: testreadwrite.c ../librfxswf.a ../libbase.a
+ $(L) -DMAIN -o testreadwrite testreadwrite.c ../librfxswf.a ../libbase.a $(LIBS)
+
+testrewrite: testrewrite.c ../librfxswf.a ../libbase.a
+ $(L) -DMAIN -o testrewrite testrewrite.c ../librfxswf.a ../libbase.a $(LIBS)
+
+testwrite: testwrite.c ../librfxswf.a ../libbase.a
+ $(L) -DMAIN -o testwrite testwrite.c ../librfxswf.a ../libbase.a $(LIBS)
+
+testpaths: testpaths.c ../librfxswf.a ../libbase.a
+ $(L) -DMAIN -o testpaths testpaths.c ../librfxswf.a ../libbase.a $(LIBS)
+
+clean:
+ rm -f *.o *.yy.c *.tab.c *.tab.h testreadwrite swfdump testpaths testwrite ../librfxswf.a
+
+.PHONY: tests
diff -Nru swftools-0.9.2+ds1/lib/as3/mkabc.py swftools-0.9.1/lib/as3/mkabc.py
--- swftools-0.9.2+ds1/lib/as3/mkabc.py 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/mkabc.py 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,167 @@
+#!/usr/bin/python
+#
+# mkops.py
+#
+# Generate opcodes.h, opcodes.h
+#
+# Copyright (c) 2008 Matthias Kramm
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+import re
+
+fi = open("code.c", "rb")
+foc = open("opcodes.c", "wb")
+foh = open("opcodes.h", "wb")
+
+foh.write("#ifndef __opcodes_h__\n")
+foh.write("#define __opcodes_h__\n")
+foh.write("#include \"abc.h\"\n")
+foh.write("#include \"pool.h\"\n")
+foh.write("#include \"code.h\"\n")
+
+foc.write("#include \"opcodes.h\"\n")
+
+R = re.compile('{(0x..),\s*"([^"]*)"\s*,\s*"([^"]*)"[^}]*}\s*')
+
+for line in fi.readlines():
+ line = line.strip()
+ m = R.match(line)
+ if m:
+ op,name,params = m.group(1),m.group(2),m.group(3)
+
+ iterations=1
+ if "2" in params or "s" in params:
+ iterations=2
+
+ for iteration in range(iterations):
+ if iteration==1:
+ name=name+"2"
+ params = params.strip()
+ paramstr = ""
+ seen = {}
+ names = []
+
+ for c in params:
+ paramstr += ", "
+ if c == "2":
+ if iteration==0:
+ type,pname="char*","name"
+ else:
+ type,pname="multiname_t*","name"
+ elif c == "s":
+ if iteration==0:
+ type,pname="char*","name"
+ else:
+ type,pname="string_t*","s"
+ elif c == "N":
+ type,pname="namespace_t*","ns"
+ elif c in "nubs":
+ type,pname="int","v"
+ elif c == "m":
+ type,pname="abc_method_t*","m"
+ elif c == "i":
+ type,pname="abc_method_body_t*","m"
+ elif c == "c":
+ type,pname="abc_class_t*","m"
+ elif c == "j":
+ type,pname="code_t*","label"
+ elif c == "S":
+ type,pname="lookupswitch_t*","l"
+ elif c == "D":
+ type,pname="void*","debuginfo"
+ elif c == "r":
+ type,pname="int","reg"
+ elif c == "f":
+ type,pname="double","f"
+ elif c == "I":
+ type,pname="int","i"
+ elif c == "U":
+ type,pname="unsigned int","u"
+ else:
+ raise "Unknown type "+c
+ paramstr += type
+ paramstr += " "
+ if pname in seen:
+ seen[pname]+=1
+ pname += str(seen[pname])
+ else:
+ seen[pname]=1
+ paramstr += pname
+ names += [pname]
+
+ foh.write("code_t* abc_%s(code_t*prev%s);\n" % (name, paramstr))
+
+ foc.write("code_t* abc_%s(code_t*prev%s)\n" % (name, paramstr))
+ foc.write("{\n")
+ foc.write(" code_t*self = add_opcode(prev, %s);\n" % op)
+ i = 0
+ for pname,c in zip(names,params):
+ if(c == "2"):
+ if iteration==0:
+ foc.write(" self->data[%d] = multiname_fromstring(%s);\n" % (i,pname));
+ else:
+ foc.write(" self->data[%d] = multiname_clone(%s);\n" % (i,pname));
+ elif(c in "nur"):
+ foc.write(" self->data[%d] = (void*)(ptroff_t)%s;\n" % (i,pname))
+ elif(c in "IU"):
+ foc.write(" self->data[%d] = (void*)(ptroff_t)%s;\n" % (i,pname))
+ elif(c in "N"):
+ foc.write(" self->data[%d] = namespace_clone(%s);\n" % (i,pname))
+ elif(c in "f"):
+ foc.write(" double*fp = malloc(sizeof(double));\n")
+ foc.write(" *fp = %s;\n" % (pname))
+ foc.write(" self->data[%d] = fp;\n" % (i))
+ elif(c == "b"):
+ foc.write(" self->data[%d] = (void*)(ptroff_t)%s;\n" % (i,pname))
+ elif(c == "s"):
+ if iteration==0:
+ foc.write(" self->data[%d] = string_new4(%s);\n" % (i,pname))
+ else:
+ foc.write(" self->data[%d] = string_dup3(%s);\n" % (i,pname))
+ elif(c == "m"):
+ foc.write(" self->data[%d] = %s;\n" % (i,pname))
+ elif(c == "c"):
+ foc.write(" self->data[%d] = %s;\n" % (i,pname))
+ elif(c == "i"):
+ foc.write(" self->data[%d] = %s;\n" % (i,pname))
+ elif(c == "j"):
+ foc.write(" self->data[%d] = 0; //placeholder\n" % i)
+ foc.write(" self->branch = %s;\n" % pname)
+ elif(c == "S"):
+ foc.write(" self->data[%d] = %s;\n" % (i,pname))
+ elif(c == "D"):
+ foc.write(" /* FIXME: write debuginfo %s */\n" % pname)
+ else:
+ raise "Unknown type "+c
+ i = i+1
+ foc.write(" return self;\n")
+ foc.write("}\n")
+
+ foh.write("#define "+name+"(")
+ foh.write(",".join(["method"]+names))
+ foh.write(") (method->code = abc_"+name+"(")
+ foh.write(",".join(["method->code"]+names))
+ foh.write("))\n")
+
+ foh.write("#define OPCODE_"+name.upper()+" "+op+"\n")
+
+foh.write("#endif\n")
+
+foh.close()
+foc.close()
+fi.close()
+#{0x75, "convert_d", ""},
+
diff -Nru swftools-0.9.2+ds1/lib/as3/mklib.c swftools-0.9.1/lib/as3/mklib.c
--- swftools-0.9.2+ds1/lib/as3/mklib.c 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/mklib.c 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,316 @@
+/* mklib.c
+
+ File to generate builtin.c
+
+ Copyright (c) 2008,2009 Matthias Kramm
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include
+#include
+#include
+#include
+#include "../rfxswf.h"
+#include "../os.h"
+#include "../q.h"
+#include "pool.h"
+#include "files.h"
+#include "tokenizer.h"
+#include "parser.tab.h"
+#include "parser.h"
+#include "import.h"
+
+void fixstring(char*s)
+{
+ char first=1;
+ for(;*s;s++) {
+ if(!((*s>='a' && *s<='z') || (*s>='A' && *s<='Z') ||
+ (*s>='0' && *s<='9' && !first))) {
+ *s = '_';
+ }
+ first = 0;
+ }
+}
+
+static char* mkpid(const char*package)
+{
+ char*id = malloc(strlen(package)+20);
+ strcpy(id, "package_");
+ if(!*package)
+ strcat(id, "global");
+ else
+ strcat(id, package);
+ fixstring(id);
+ return id;
+}
+static char* mkcid(const char*package, const char*name)
+{
+ char*id = malloc(strlen(package)+strlen(name)+10);
+ strcpy(id, package);
+ strcat(id, "_");
+ strcat(id, name);
+ fixstring(id);
+ return id;
+}
+static char* mkptr2(const char*package, const char*name)
+{
+ if(!package[0] && !strcmp(name, "void")) {
+ return "&voidclass";
+ }
+ char*id = malloc(strlen(package)+strlen(name)+10);
+ strcpy(id, "&");
+ strcat(id, package);
+ strcat(id, "_");
+ strcat(id, name);
+ fixstring(id+1);
+ return id;
+}
+static char* mkid2(const char*cls, const char*member)
+{
+ char*id = malloc(strlen(cls)+strlen(member)+10);
+ strcpy(id, cls);
+ strcat(id, "_");
+ strcat(id, member);
+ fixstring(id);
+ return id;
+}
+#define mkid(s) ((s)?mkcid((s)->package, (s)->name):"0")
+#define mkptr(s) ((s)?mkptr2((s)->package, (s)->name):"0")
+
+static array_t*tosort=0;
+static int compare_classes(const void*v1, const void*v2)
+{
+ int x1 = *(int*)v1;
+ int x2 = *(int*)v2;
+ abc_class_t*c1 = array_getvalue(tosort, x1);
+ abc_class_t*c2 = array_getvalue(tosort, x2);
+ int i = strcmp(c1->classname->ns->name, c2->classname->ns->name);
+ if(i)
+ return i;
+ return strcmp(c1->classname->name, c2->classname->name);
+}
+
+static int compare_traits(const void*v1, const void*v2)
+{
+ trait_t* x1 = *(trait_t**)v1;
+ trait_t* x2 = *(trait_t**)v2;
+ int i = strcmp(x1->name->ns->name, x2->name->ns->name);
+ if(i)
+ return i;
+ return strcmp(x1->name->name, x2->name->name);
+}
+
+dict_t* builtin_getclasses()
+{
+ return dict_new2(&slotinfo_type);
+}
+
+extern dict_t*registry_classes;
+
+char*mktype(slotinfo_t*s)
+{
+ if(s->kind == INFOTYPE_CLASS) {
+ return "classinfo_t";
+ } else if(s->kind == INFOTYPE_METHOD) {
+ return "methodinfo_t";
+ } else if(s->kind == INFOTYPE_VAR) {
+ return "varinfo_t";
+ }
+ return "**ERROR**";
+}
+
+void write_slotinfo(FILE*fi, slotinfo_t*s, char*id, char*prefix);
+
+void write_slotinfo_decl(FILE*fi, slotinfo_t*s, char*prefix)
+{
+ fprintf(fi, "%s", prefix);
+ char*id = mkid(s);
+ fprintf(fi, "static %s %s;\n", mktype(s), id);
+
+ if(s->kind == INFOTYPE_CLASS) {
+ classinfo_t*c = (classinfo_t*)s;
+ dict_t*d = &c->members;
+ DICT_ITERATE_DATA(d, slotinfo_t*, s1) {
+ fprintf(fi, "static %s %s;\n", mktype(s1), mkid2(id, s1->name));
+ }
+ DICT_ITERATE_DATA(d, slotinfo_t*, s2) {
+ fprintf(fi, "static %s %s;\n", mktype(s2), mkid2(id, s2->name));
+ }
+ }
+}
+void write_initinfo(FILE*fi, slotinfo_t*s, char*prefix)
+{
+ if(s->kind == INFOTYPE_CLASS) {
+ classinfo_t*c = (classinfo_t*)s;
+ char*id = mkid(c);
+ dict_t*d1 = &c->members;
+ dict_t*d2 = &c->static_members;
+ fprintf(fi, "%s", prefix);
+ fprintf(fi, "dict_init2(&%s.members, &memberinfo_type, %d);\n", id, d1->hashsize);
+ fprintf(fi, "%s", prefix);
+ fprintf(fi, "dict_init2(&%s.static_members, &memberinfo_type, %d);\n", id, d2->hashsize);
+ int t;
+ DICT_ITERATE_DATA(d1,slotinfo_t*,s1) {
+ fprintf(fi, "%s", prefix);
+ char*id2 = mkid2(id, s1->name);
+ fprintf(fi, "dict_put(&%s.members, &%s, &%s);\n", id, id2, id2);
+ }
+ DICT_ITERATE_DATA(d2,slotinfo_t*,s2) {
+ fprintf(fi, "%s", prefix);
+ char*id2 = mkid2(id, s2->name);
+ fprintf(fi, "dict_put(&%s.static_members, &%s, &%s);\n", id, id2, id2);
+ }
+ }
+}
+
+void write_constant(FILE*fi, constant_t*value, char*id, char*prefix)
+{
+ if(NS_TYPE(value->type)) {
+ fprintf(fi, "%s", prefix);
+ fprintf(fi, "static namespace_t %s_constant_ns = {0x%02x, \"%s\"};\n", id, value->ns->access, value->ns->name);
+ } else if(value->type == CONSTANT_STRING) {
+ fprintf(fi, "%s", prefix);
+ fprintf(fi, "static string_t %s_constant_s = {\"%s\", %d};\n", id, value->s->str, value->s->len);
+ }
+ fprintf(fi, "%s", prefix);
+ fprintf(fi, "static constant_t %s_constant = ", id);
+ fprintf(fi, "{type: %d", value->type);
+ if(NS_TYPE(value->type)) {
+ fprintf(fi, ", &%s_constant_ns", id);
+ } else if(value->type == CONSTANT_INT) {
+ fprintf(fi, ",i: %d,", value->type);
+ } else if(value->type == CONSTANT_UINT) {
+ fprintf(fi, ",u: %u", value->u);
+ } else if(value->type == CONSTANT_FLOAT) {
+ if(!isnan(value->f) && !isinf(value->f))
+ fprintf(fi, ", %f", value->f);
+ } else if(value->type == CONSTANT_STRING) {
+ fprintf(fi, ", &%s_constant_s", id);
+ }
+ fprintf(fi, "};\n");
+}
+
+void write_slotinfo(FILE*fi, slotinfo_t*s, char*id, char*prefix)
+{
+ if(s->kind == INFOTYPE_VAR) {
+ varinfo_t*v = (varinfo_t*)s;
+ if(v->value) {
+ write_constant(fi, v->value, id, prefix);
+ }
+ }
+ fprintf(fi, "%s", prefix);
+ fprintf(fi, "static %s %s = {", mktype(s), id);
+ fprintf(fi, "0x%02x, 0x%02x, 0x%02x, 0x%02x, ", s->kind, s->subtype, s->flags, s->access);
+ if(s->package)
+ fprintf(fi, "\"%s\", ", s->package);
+ else
+ fprintf(fi, "0, ");
+
+ if(s->name)
+ fprintf(fi, "\"%s\", ", s->name);
+ else
+ fprintf(fi, "0, ");
+
+ fprintf(fi, "%d, ", s->slot);
+
+ if(s->kind == INFOTYPE_CLASS) {
+ classinfo_t*c = (classinfo_t*)s;
+ fprintf(fi, "%s, ", mkptr(c->superclass));
+ fprintf(fi, "interfaces: {");
+ int t;
+ for(t=0;c->interfaces[t];t++) {
+ fprintf(fi, "%s", mkptr(c->interfaces[t]));
+ fprintf(fi, ", ");
+ }
+ fprintf(fi, "0}};\n");
+ }
+ if(s->kind == INFOTYPE_METHOD) {
+ methodinfo_t*m = (methodinfo_t*)s;
+ fprintf(fi, "%s, ", mkptr(m->return_type));
+ fprintf(fi, "%s, ", mkptr(m->parent));
+ fprintf(fi, "0"); // params TODO
+ fprintf(fi, "};\n");
+ }
+ if(s->kind == INFOTYPE_VAR) {
+ varinfo_t*m = (varinfo_t*)s;
+ fprintf(fi, "%s, ", mkptr(m->type));
+ fprintf(fi, "%s, ", mkptr(m->parent));
+ if(!m->value) fprintf(fi, "0");
+ else fprintf(fi, "&%s_constant", id);
+ fprintf(fi, "};\n");
+ }
+
+ if(s->kind == INFOTYPE_CLASS) {
+ classinfo_t*c = (classinfo_t*)s;
+ dict_t*d = &c->members;
+ DICT_ITERATE_DATA(d, slotinfo_t*, s1) {
+ write_slotinfo(fi, s1, mkid2(id,s1->name), prefix);
+ }
+ d = &c->static_members;
+ DICT_ITERATE_DATA(d, slotinfo_t*, s2) {
+ write_slotinfo(fi, s2, mkid2(id,s2->name), prefix);
+ }
+ }
+}
+
+int main()
+{
+ registry_classes = builtin_getclasses();
+
+ as3_import_abc("builtin.abc");
+ as3_import_abc("playerglobal.abc");
+
+ FILE*fi = fopen("builtin.c", "wb");
+
+ int t;
+ int pass;
+
+
+ for(pass=1;pass<=3;pass++) {
+ if(pass==1) {
+ fprintf(fi, "#include \"builtin.h\"\n");
+ fprintf(fi, "\n");
+ }
+ if(pass==3) {
+ fprintf(fi, "dict_t* builtin_getclasses()\n");
+ fprintf(fi, "{\n");
+ fprintf(fi, " dict_t*d = dict_new2(&slotinfo_type);\n");
+ }
+ for(t=0;thashsize;t++) {
+ dictentry_t*l = registry_classes->slots[t];
+ while(l) {
+ slotinfo_t*s = (slotinfo_t*)l->key;
+ //printf("%08x %s %s\n", s, s->package, s->name);
+ char*id = mkid(s);
+ if(pass==1) {
+ write_slotinfo_decl(fi, s, "");
+ }
+ if(pass==2) {
+ write_slotinfo(fi, s, mkid(s), "");
+ }
+ if(pass==3) {
+ fprintf(fi, " dict_put(d, &%s, &%s);\n", id, id);
+ write_initinfo(fi, s, " ");
+ }
+ l = l->next;
+ }
+ }
+ }
+ fprintf(fi, " _NaN_constant.f = __builtin_nan(\"\");\n");
+ fprintf(fi, " _Infinity_constant.f = __builtin_inf();\n");
+ fprintf(fi, " return d;\n");
+ fprintf(fi, "}\n");
+ return 0;
+}
diff -Nru swftools-0.9.2+ds1/lib/as3/notes.txt swftools-0.9.1/lib/as3/notes.txt
--- swftools-0.9.2+ds1/lib/as3/notes.txt 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/notes.txt 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,154 @@
+-----------------------------------------------------------------------
+
+ var x = a
+ [ExcludeClass(...)]
+
+[x=a at [ExcludeClass(...)] or x=a, then embed command?]
+
+-----------------------------------------------------------------------
+
+ if(1==2)
+ return
+ i++
+
+[return i++ or just return?]
+
+-----------------------------------------------------------------------
+
+ x = 3
+ /abc/
+ y++
+
+[x=3;regexp abc;y++ or x divided by abc divided by y++?]
+
+-----------------------------------------------------------------------
+
+ x = 5
+ -obj
+
+[x=5, evaluate "minus obj" or x=5-obj?]
+
+-----------------------------------------------------------------------
+
+ x = y as X.z
+
+[coerce y to static field z of X, or coerce y to X, then evaluate member z?]
+
+-----------------------------------------------------------------------
+ if(1==2)
+ return
+ { myloop: i++;}
+
+[return object:{myloop:i++} or execute code block with myloop label?]
+
+
+-----------------------------------------------------------------------
+
+ for(i in a in a; ...)
+
+[only after encountering the first ; it becomes clear that this is in
+ fact *not* a for-in loop]
+
+-----------------------------------------------------------------------
+
+ var x =
+ namespace1 ++ namespace2
+ function test()
+ {
+ }
+
+[x = namespace1, increment namespace2? or is test in namespace2?]
+
+-----------------------------------------------------------------------
+
+
+ x = (a[Math.random(100)] += 10)
+
+code needed for this:
+
+ push a
+ calculate Math.random(100), push
+ dup2 [a.k.a. setlocal tmp, dup , getlocal tmp, swap, getlocal tmp]
+ getproperty (consumes two stack values)
+ [code for adding 10]
+ setlocal tmp (we don't have *any* kind of useful stack exchange operations, so no way around a local register)
+ setproperty (consumes two stack values again)
+ getlocal tmp
+ kill tmp (so the verifier is happy)
+ setlocal x (finally!)
+
+-----------------------------------------------------------------------
+
+VerifyError: Error #1030: Stack depth is unbalanced. 0 != 1.
+
+0 : local position
+1 : position I'm jumping to
+
+-----------------------------------------------------------------------
+
+Verifier is buggy:
+
+verify test.package::Main()
+ stack:
+ scope: [global Object$ flash.events::EventDispatcher$ flash.display::DisplayObject$ flash.display::InteractiveObject$ flash.display::DisplayObjectContainer$ flash.display::Sprite$ flash.display::MovieClip$ test.package::Main$]
+ locals: test.package::Main
+ 0:getlocal0
+ stack: test.package::Main
+ scope: [global Object$ flash.events::EventDispatcher$ flash.display::DisplayObject$ flash.display::InteractiveObject$ flash.display::DisplayObjectContainer$ flash.display::Sprite$ flash.display::MovieClip$ test.package::Main$]
+ locals: test.package::Main
+ 1:pushscope
+ stack:
+ scope: [global Object$ flash.events::EventDispatcher$ flash.display::DisplayObject$ flash.display::InteractiveObject$ flash.display::DisplayObjectContainer$ flash.display::Sprite$ flash.display::MovieClip$ test.package::Main$] test.package::Main
+ locals: test.package::Main
+ 2:jump 7
+B0:
+ stack:
+ scope: [global Object$ flash.events::EventDispatcher$ flash.display::DisplayObject$ flash.display::InteractiveObject$ flash.display::DisplayObjectContainer$ flash.display::Sprite$ flash.display::MovieClip$ test.package::Main$] test.package::Main
+ locals: test.package::Main?
+ 6:label
+B1:
+ stack:
+ scope: [global Object$ flash.events::EventDispatcher$ flash.display::DisplayObject$ flash.display::InteractiveObject$ flash.display::DisplayObjectContainer$ flash.display::Sprite$ flash.display::MovieClip$ test.package::Main$] test.package::Main?
+ locals: test.package::Main?
+ 7:label
+ stack:
+ scope: [global Object$ flash.events::EventDispatcher$ flash.display::DisplayObject$ flash.display::InteractiveObject$ flash.display::DisplayObjectContainer$ flash.display::Sprite$ flash.display::MovieClip$ test.package::Main$] test.package::Main?
+ locals: test.package::Main?
+ 8:pushfalse
+ stack: Boolean
+ scope: [global Object$ flash.events::EventDispatcher$ flash.display::DisplayObject$ flash.display::InteractiveObject$ flash.display::DisplayObjectContainer$ flash.display::Sprite$ flash.display::MovieClip$ test.package::Main$] test.package::Main?
+ locals: test.package::Main?
+ 9:iftrue 6
+VerifyError: Error #1068: test.package.Main and test.package.Main cannot be reconciled.
+
+ at test.package::Main()
+
+
+static void xx_scopetest()
+{
+ /* findpropstrict doesn't just return a scope object- it
+ also makes it "active" somehow. Push local_0 on the
+ scope stack and read it back with findpropstrict, it'll
+ contain properties like "trace". Trying to find the same
+ property on a "vanilla" local_0 yields only a "undefined" */
+ //c = abc_findpropstrict(c, "[package]::trace");
+
+ /*c = abc_getlocal_0(c);
+ c = abc_findpropstrict(c, "[package]::trace");
+ c = abc_coerce_a(c);
+ c = abc_setlocal_1(c);
+
+ c = abc_pushbyte(c, 0);
+ c = abc_setlocal_2(c);
+
+ code_t*xx = c = abc_label(c);
+ c = abc_findpropstrict(c, "[package]::trace");
+ c = abc_pushstring(c, "prop:");
+ c = abc_hasnext2(c, 1, 2);
+ c = abc_dup(c);
+ c = abc_setlocal_3(c);
+ c = abc_callpropvoid(c, "[package]::trace", 2);
+ c = abc_getlocal_3(c);
+ c = abc_kill(c, 3);
+ c = abc_iftrue(c,xx);*/
+}
diff -Nru swftools-0.9.2+ds1/lib/as3/ok/anonymous_functions.as swftools-0.9.1/lib/as3/ok/anonymous_functions.as
--- swftools-0.9.2+ds1/lib/as3/ok/anonymous_functions.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/ok/anonymous_functions.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,28 @@
+package {
+ import flash.display.MovieClip
+ import flash.geom.Point
+
+ public var func:Function = function(nr:uint) {trace("ok "+nr+"/4");}
+
+ public class Main extends flash.display.MovieClip {
+
+ function run(f:Function, text:String) {
+ f(text);
+ }
+
+ public function Main() {
+ var log = function(text) {
+ trace(text);
+ }
+ log("ok 1/4");
+ var l = log;
+ l("ok 2/4");
+
+ run(function(text) {trace(text)}, "ok 3/4")
+
+ func(4);
+
+ trace("[exit]");
+ }
+ }
+}
diff -Nru swftools-0.9.2+ds1/lib/as3/ok/arguments.as swftools-0.9.1/lib/as3/ok/arguments.as
--- swftools-0.9.2+ds1/lib/as3/ok/arguments.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/ok/arguments.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,62 @@
+package {
+ import flash.display.MovieClip
+
+ public class Main extends flash.display.MovieClip {
+
+ public function f(x,y) {
+ var z = arguments;
+ trace(z[0]);
+ trace(z[1]);
+ }
+
+ function test_function()
+ {
+ f("ok 1/8","ok 2/8");
+ }
+ function test_innerfunction()
+ {
+ var z = function(x,y) {
+ var z = arguments;
+ trace(z[0]);
+ trace(z[1]);
+ }
+ z("ok 3/8", "ok 4/8");
+ }
+ function test_innerslotfunction()
+ {
+ var i = 0;
+ var z = function(x,y) {
+ var v = arguments;
+ trace(v[0]);
+ trace(v[1]);
+ i++;
+ }
+ z("ok 5/8", "ok 6/8");
+ if(i!=1)
+ trace("error");
+ }
+ function test_slottedfunction(r1:String, r2:String)
+ {
+ var z = arguments;
+ if(!(z instanceof Array))
+ trace("error");
+ if(!(r1 instanceof String))
+ trace("error");
+ if(!(r2 instanceof String))
+ trace("error");
+ function inner() {
+ trace(z[0]);
+ trace(z[1]);
+ }
+ inner();
+ }
+
+ function Main() {
+ test_function();
+ test_innerfunction();
+ test_innerslotfunction();
+ test_slottedfunction("ok 7/8", "ok 8/8");
+ trace("[exit]");
+ }
+ }
+}
diff -Nru swftools-0.9.2+ds1/lib/as3/ok/arrays.as swftools-0.9.1/lib/as3/ok/arrays.as
--- swftools-0.9.2+ds1/lib/as3/ok/arrays.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/ok/arrays.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,30 @@
+
+package {
+ import flash.display.MovieClip;
+
+ public class Main extends flash.display.MovieClip {
+ function Main() {
+ var a:Array = new Array(1,2,3);
+ if(a[0]==1) trace("ok 1/10");
+ if(a[1]==2) trace("ok 2/10");
+ if(a[2]==3) trace("ok 3/10");
+ if(a.length==3) trace("ok 4/10");
+
+ var b:Array = [1,2,3];
+ if(b[0]==1) trace("ok 5/10");
+ if(b[1]==2) trace("ok 6/10");
+ if(b[2]==3) trace("ok 7/10");
+ if(b.length==3) trace("ok 8/10");
+
+ // test for ]+ parser bug:
+ var check = (3 == a[0]+1);
+
+ var list:Array = ["ok 9/10", "ok 10/10"];
+ for each(var s:String in list) {
+ trace(s);
+ }
+
+ trace("[exit]");
+ }
+ }
+}
diff -Nru swftools-0.9.2+ds1/lib/as3/ok/assignments.as swftools-0.9.1/lib/as3/ok/assignments.as
--- swftools-0.9.2+ds1/lib/as3/ok/assignments.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/ok/assignments.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,68 @@
+
+package {
+ import flash.display.MovieClip
+
+ public class Main extends flash.display.MovieClip {
+
+ var count:int = 1;
+ var num:int = 18;
+
+ function assert(b:Boolean) {
+ if(b) {
+ trace("ok "+count+"/"+num);
+ } else {
+ trace("error "+count+"/"+num);
+ }
+ count = count + 1
+ }
+
+ function Main() {
+ var x:int = 0;
+ var y:int = 0;
+
+ /* test that assignment expressions do indeed return the
+ right value */
+ x = (y=1); assert(x==1 && y==1); //x=1;y=1;
+ x = (y++); assert(x==1 && y==2); //x=1;y=2;
+ x = (y--); assert(x==2 && y==1); //x=2;y=1;
+ x = (++y); assert(x==2 && y==2); //x=2;y=2;
+ x = (--y); assert(x==1 && y==1); //x=1;y=1;
+ x = (y += 1);assert(x==2 && y==2); //x=2;y=2;
+ x = (y -= 1);assert(x==1 && y==1); //x=1;y=1;
+ x = y = 5; assert(x==5 && y==5); //x=5;y=5;
+
+ y = 5;
+ x = (y*=5); assert(x==25 && y==25);
+ x = (y%=7); assert(x==4 && y==4);
+ x = (y<<=1); assert(x==8 && y==8);
+ x = (y>>=1); assert(x==4 && y==4);
+ x = (y>>>=1); assert(x==2 && y==2);
+ y = 2;
+ x = (y/=2); assert(x==1 && y==1);
+ x = 0x55;
+ x |= 0x0f; assert(x==0x5f);
+
+ x=3;y=3;
+ x ^= 7;
+ y = y^7;
+ assert(x==y);
+
+ x = 0x55;
+ y = 0x0f;
+ x &= y;
+ assert(x==0x05);
+
+ /* nested assignment expressions need different temporary
+ registers- make sure they don't collide */
+ var a:int = 1;
+ var b:int = 2;
+ var c:int = 3;
+ var d:int = 4;
+ a += b += c += d += 1
+ assert(a==11 && b==10 && c==8 && d==5);
+
+ trace("[exit]");
+ }
+ }
+}
+
diff -Nru swftools-0.9.2+ds1/lib/as3/ok/boolvalue.as swftools-0.9.1/lib/as3/ok/boolvalue.as
--- swftools-0.9.2+ds1/lib/as3/ok/boolvalue.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/ok/boolvalue.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,42 @@
+package {
+ import flash.display.MovieClip;
+ public class Main extends flash.display.MovieClip {
+
+ function ok1():Boolean {trace("ok 7/16");return true;}
+ function ok2():Boolean {trace("ok 9/16");return true;}
+ function ok3():Boolean {trace("ok 13/16");return true;}
+ function ok4():Boolean {trace("ok 15/16");return true;}
+
+ function error():Boolean {trace("error");return true;}
+
+ function Main() {
+ trace(false || "ok 1/16");
+ trace("ok 2/16" || "error");
+
+ if(false && true) trace("error") else trace("ok 3/16");
+ trace("error" && "ok 4/16");
+
+ if(!false) trace("ok 5/16");
+
+ if(!true) trace("error");
+ else trace("ok 6/16");
+
+ /* test left associativity for && */
+ if(true && true && ok1()) trace("ok 8/16");
+ if(false && true && error()) trace("error");
+ if(true && false && error()) trace("error");
+ if(true && ok2() && false) trace("error1");
+ if(false && error() && true) trace("error2");
+
+ if(false || false || true || error()) trace("ok 10/16");
+
+ /* test left associativity for || */
+ if(true || false || error()) trace("ok 11/16");
+ if(true || error() || false) trace("ok 12/16");
+ if(ok3() || true || true) trace("ok 14/16");
+ if(false || false || ok4()) trace("ok 16/16");
+
+ trace("[exit]");
+ }
+ }
+}
diff -Nru swftools-0.9.2+ds1/lib/as3/ok/boundmethod.as swftools-0.9.1/lib/as3/ok/boundmethod.as
--- swftools-0.9.2+ds1/lib/as3/ok/boundmethod.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/ok/boundmethod.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,29 @@
+package {
+ import flash.display.MovieClip;
+
+ public class Other {
+ var a="ok 3/3";
+
+ function print2() {
+ trace(this.a);
+ }
+ }
+
+ public class Main extends flash.display.MovieClip {
+ internal var r;
+ function print(s) {
+ trace(s);
+ trace(this.r);
+ }
+ function Main() {
+ var x = this.print;
+ this.r = "ok 2/3";
+ x("ok 1/3");
+
+ x = (new Other).print2;
+ x();
+
+ trace("[exit]");
+ }
+ }
+}
diff -Nru swftools-0.9.2+ds1/lib/as3/ok/break.as swftools-0.9.1/lib/as3/ok/break.as
--- swftools-0.9.2+ds1/lib/as3/ok/break.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/ok/break.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,47 @@
+package test.package {
+ public class Main extends flash.display.MovieClip {
+ function Main() {
+ var i:int;
+ /* test breaking loop */
+ for(i=0;i<100;i++) {
+ var x=-1;
+ if(i*i==49)
+ break;
+ }
+ if(i!=7) trace("error");
+ else trace("ok 1/4");
+
+ /* test not breaking loop */
+ for(;i<10;i++) {
+ var x="String";
+ if(i==20)
+ break;
+ }
+ if(i!=10) trace("error");
+ else trace("ok 2/4");
+
+ /* test breaking while */
+ while(i<20) {
+ var x=1.0;
+ if(i==15)
+ break;
+ i++;
+ }
+ if(i!=15) trace("error");
+ else trace("ok 3/4");
+
+ /* test non-breaking while */
+ while(i<30) {
+ var x=new Object;
+ if(i==40)
+ break;
+ i++;
+ }
+ if(i!=30) trace("error");
+ else trace("ok 4/4");
+
+ trace("[exit]");
+ }
+ }
+}
+
diff -Nru swftools-0.9.2+ds1/lib/as3/ok/break-label.as swftools-0.9.1/lib/as3/ok/break-label.as
--- swftools-0.9.2+ds1/lib/as3/ok/break-label.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/ok/break-label.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,44 @@
+package {
+ import flash.display.MovieClip
+ public class Main extends flash.display.MovieClip {
+ function Main() {
+ var i,j,k;
+
+ outerloop:
+ for(i=0;i<100;i++) {
+ var x1:String;
+ for(j=0;j<100;j++) {
+ var x2:String;
+ for(k=0;k<100;k++) {
+ var x3:String;
+ trace("ok 1/2");
+ break outerloop;
+ trace("error");
+ }
+ trace("error");
+ }
+ trace("error");
+ }
+
+ for(i=0;i<100;i++) {
+ var x1:String;
+ midloop:
+ for(j=0;j<100;j++) {
+ var x2:String;
+ for(k=0;k<100;k++) {
+ var x3:String;
+ trace("ok 2/2");
+ break midloop;
+ trace("error");
+ }
+ trace("error");
+ }
+ break;
+ trace("error");
+ }
+
+ trace("[exit]");
+ }
+ }
+}
+
diff -Nru swftools-0.9.2+ds1/lib/as3/ok/cdata.as swftools-0.9.1/lib/as3/ok/cdata.as
--- swftools-0.9.2+ds1/lib/as3/ok/cdata.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/ok/cdata.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,19 @@
+package {
+ import flash.display.MovieClip
+
+ public class Main extends flash.display.MovieClip {
+
+ function test()
+ {
+ return (]]].]].]>.]]]>).toString();
+ }
+
+ function Main() {
+ if(this.test() == "[0][]]<]>]]].]].]>.]")
+ trace("ok");
+ else
+ trace("error");
+ trace("[exit]");
+ }
+ }
+}
diff -Nru swftools-0.9.2+ds1/lib/as3/ok/class1.as swftools-0.9.1/lib/as3/ok/class1.as
--- swftools-0.9.2+ds1/lib/as3/ok/class1.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/ok/class1.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,56 @@
+package test1 {
+
+ import flash.display.MovieClip
+
+ public class Test {
+ protected var num6:Number = 0;
+
+ public function g()
+ {
+ trace("ok "+num6+"/6");
+ }
+ }
+ public class ExtendTest extends Test {
+ public function f()
+ {
+ // test super
+ super.num6 = 6;
+ }
+ }
+
+ public class Main extends flash.display.MovieClip {
+
+ const ok1:String = "ok 1/6", ok2:String = "ok 2/6";
+ var ok3:String = "ok 3/6", ok4:String = "ok 4/6";
+ var num5:Number = 4;
+
+ var xx:Main=null;
+ function Main() {
+ trace(ok1);
+ trace(this.ok2);
+ trace(this.ok3);
+ trace(ok4);
+
+ num5++;
+ trace("ok "+num5+"/6");
+
+ var p = new ExtendTest();
+ p.f();
+ p.g();
+
+ trace("[exit]");
+ }
+
+ }
+ /* explicitly internal */
+ internal class InternalClass {
+ }
+ /* implicitly internal */
+ class ImplicitInternalClass {
+ }
+
+}
+package test2 {
+ public class PublicClass extends test1.Main {
+ }
+}
diff -Nru swftools-0.9.2+ds1/lib/as3/ok/classinit.as swftools-0.9.1/lib/as3/ok/classinit.as
--- swftools-0.9.2+ds1/lib/as3/ok/classinit.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/ok/classinit.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,26 @@
+
+package {
+ import flash.display.MovieClip
+ import flash.system.Capabilities
+ public class Main extends flash.display.MovieClip {
+
+ static var mode = 3;
+ static var message="error";
+
+ /* test code which executes directly in the class' static
+ constructor */
+ if(mode == 3)
+ message = "ok 1/1";
+ else
+ message = "error";
+
+ /* test access to other classes static fields during our init code */
+ static var os;
+ os = Capabilities.os;
+
+ function Main() {
+ trace(Main.message);
+ trace("[exit]");
+ }
+ }
+}
diff -Nru swftools-0.9.2+ds1/lib/as3/ok/classorder2.as swftools-0.9.1/lib/as3/ok/classorder2.as
--- swftools-0.9.2+ds1/lib/as3/ok/classorder2.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/ok/classorder2.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,35 @@
+package {
+
+ public class E {
+ }
+
+ public class A extends E {
+ static var x = D.d();
+ trace("ok 4/4");
+ }
+ public class B {
+ static var x = C.c();
+ trace("ok 2/4");
+ static function b() {
+ }
+ }
+ public class C extends E {
+ trace("ok 1/4");
+ static function c() {
+ }
+ }
+ public class D {
+ static var x = C.c();
+ trace("ok 3/4");
+ if(B.b) {}
+ static function d() {
+ }
+ }
+
+ import flash.display.MovieClip;
+ public class Main extends MovieClip {
+ function Main() {
+ trace("[exit]");
+ }
+ }
+}
diff -Nru swftools-0.9.2+ds1/lib/as3/ok/classorder.as swftools-0.9.1/lib/as3/ok/classorder.as
--- swftools-0.9.2+ds1/lib/as3/ok/classorder.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/ok/classorder.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,34 @@
+package {
+ import flash.display.MovieClip
+ import flash.utils.ByteArray
+
+ public interface I10 {}
+ public interface I2 extends I10,I1 {}
+ public interface I8 extends I10,I3 {}
+ public interface I9 extends I10,I8 {}
+ public interface I3 extends I10,I1 {}
+ public interface I5 extends I10,I1 {}
+ public interface I7 extends I10,I5 {}
+ public interface I6 extends I10,I5 {}
+ public interface I4 extends I10,I2 {}
+ public interface I1 {}
+
+
+ public class C2 extends C1 implements I3 {}
+ public class C8 extends C3 implements I4 {}
+ public class C9 extends C8 implements I5,I2 {}
+ public class C3 extends C1 implements I8, I1 {}
+ public class C5 extends C1 implements I9, I5, I6 {}
+ public class C7 extends C5 implements I3 {}
+ public class C6 extends C5 implements I4 {}
+ public class C4 extends C2 implements I1, I4{}
+ public class C1 implements I8, I2 {}
+
+ public class Main extends MovieClip {
+ function Main() {
+ var c:C9 = new C9;
+ trace("ok");
+ trace("[exit]");
+ }
+ }
+}
diff -Nru swftools-0.9.2+ds1/lib/as3/ok/compare.as swftools-0.9.1/lib/as3/ok/compare.as
--- swftools-0.9.2+ds1/lib/as3/ok/compare.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/ok/compare.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,38 @@
+package test.package {
+ public class Main extends flash.display.MovieClip {
+ function Main() {
+ var a=3;
+ var b=10;
+ var c=15;
+ var d=10;
+
+ if(a=d) trace("ok 5/18");else trace("error");
+ if(b<=d) trace("ok 6/18");else trace("error");
+
+ if(a<=b) trace("ok 7/18");else trace("error");
+ if(b<=c) trace("ok 8/18");else trace("error");
+ if(a<=c) trace("ok 9/18");else trace("error");
+
+ if(b>=a) trace("ok 10/18");else trace("error");
+ if(c>=b) trace("ok 11/18");else trace("error");
+ if(c>=a) trace("ok 12/18");else trace("error");
+
+ if(b>a) trace("ok 13/18");else trace("error");
+ if(c>b) trace("ok 14/18");else trace("error");
+ if(c>a) trace("ok 15/18");else trace("error");
+
+ if(bd) trace("error");else trace("ok 17/18");
+
+ trace("ok 18/18");
+
+ trace("[exit]");
+ }
+ }
+}
+
diff -Nru swftools-0.9.2+ds1/lib/as3/ok/compareseq.as swftools-0.9.1/lib/as3/ok/compareseq.as
--- swftools-0.9.2+ds1/lib/as3/ok/compareseq.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/ok/compareseq.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,42 @@
+package {
+ import flash.display.MovieClip
+
+ public class Main extends flash.display.MovieClip {
+
+ var count:int = 1;
+ var num:int = 16;
+
+ function istrue(b:Boolean) {
+ if(b) {
+ trace("ok "+count+"/"+num);
+ } else {
+ trace("error "+count+"/"+num);
+ }
+ count = count + 1
+ }
+ function isfalse(b:Boolean) {
+ istrue(!b);
+ }
+
+ function Main() {
+ trace("ok");
+
+ istrue(1 < 2 < 3);
+ isfalse(2 < 1 < 3);
+ isfalse(3 < 2 < 1);
+ isfalse(1 < 3 < 2);
+ isfalse(2 < 3 < 1);
+ isfalse(3 < 1 < 2);
+
+ isfalse(1 > 2 > 3);
+ isfalse(2 > 1 > 3);
+ istrue(3 > 2 > 1);
+ isfalse(1 > 3 > 2);
+ isfalse(2 > 3 > 1);
+ isfalse(3 > 1 > 2);
+
+ trace("[exit]");
+ }
+ }
+}
+
diff -Nru swftools-0.9.2+ds1/lib/as3/ok/conditionalcompile.as swftools-0.9.1/lib/as3/ok/conditionalcompile.as
--- swftools-0.9.2+ds1/lib/as3/ok/conditionalcompile.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/ok/conditionalcompile.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,20 @@
+package test1 {
+
+ import flash.display.MovieClip
+
+ var x;
+
+ TEST::DEBUG {
+ import jj.xx.jj;
+ var x:int;
+ x();
+ }
+
+ public class Main extends flash.display.MovieClip {
+ function Main() {
+ trace("ok");
+ trace("[exit]");
+ }
+
+ }
+}
diff -Nru swftools-0.9.2+ds1/lib/as3/ok/const.as swftools-0.9.1/lib/as3/ok/const.as
--- swftools-0.9.2+ds1/lib/as3/ok/const.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/ok/const.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,36 @@
+package {
+ import flash.display.MovieClip
+ public class Main extends flash.display.MovieClip {
+
+ const ok1:String = "ok 1/6";
+ static const ok2:String = "ok 2/6";
+
+ const ok3:String = "ok 3/6";
+ static const ok4:String = "ok 4/6";
+
+ const ok5:String = "ok 5/6";
+ static const ok6:String = "ok "+"6/6";
+
+ function Main() {
+ trace(ok1);
+ trace(ok2);
+ trace(this.ok3);
+ trace(Main.ok4);
+ f1();
+ f2();
+
+ trace("[exit]");
+ }
+ function f0(x:Number=1000)
+ {
+ }
+ function f1(x:String=ok5)
+ {
+ trace(x);
+ }
+ function f2(x:String=ok6)
+ {
+ trace(x);
+ }
+ }
+}
diff -Nru swftools-0.9.2+ds1/lib/as3/ok/constructorfunc.as swftools-0.9.1/lib/as3/ok/constructorfunc.as
--- swftools-0.9.2+ds1/lib/as3/ok/constructorfunc.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/ok/constructorfunc.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,30 @@
+package {
+ import flash.display.MovieClip;
+
+ public class Main extends flash.display.MovieClip {
+ function Main() {
+ function FooBar(x,y) {
+ this.x = x;
+ this.y = y;
+ this.ok4 = "ok 4/5";
+ this.f1 = function() {
+ trace(this.ok4);
+ }
+ };
+ FooBar.prototype.z = "ok 3/5";
+ FooBar.prototype.f2 = function () {
+ trace(this.ok5);
+ }
+
+ var foobar = new FooBar("ok 1/5", "ok 2/5");
+ foobar.ok5 = "ok 5/5";
+ trace(foobar.x);
+ trace(foobar.y);
+ trace(foobar.z);
+ foobar.f1();
+ foobar.f2();
+
+ trace("[exit]");
+ }
+ }
+}
diff -Nru swftools-0.9.2+ds1/lib/as3/ok/continue.as swftools-0.9.1/lib/as3/ok/continue.as
--- swftools-0.9.2+ds1/lib/as3/ok/continue.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/ok/continue.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,44 @@
+package {
+ import flash.display.MovieClip
+ public class Main extends flash.display.MovieClip {
+ function Main() {
+ var i:int;
+
+ /* test for loop */
+ var j:int=0;
+ for(i=0;i<100;i++) {
+ j++;
+ if(i!=50)
+ continue;
+ trace("ok 1/6");
+ }
+ if(j==100)
+ trace("ok 2/6");
+
+ /* test while loop */
+ while(i++<200) {
+ j++;
+ if(i!=150)
+ continue;
+ trace("ok 3/6");
+ }
+ if(j==200)
+ trace("ok 4/6");
+
+ /* test do-while loop */
+
+ do {
+ j++;
+ if(i!=250)
+ continue;
+ trace("ok 5/6");
+ } while(i++<300);
+
+ if(j==300)
+ trace("ok 6/6");
+
+ trace("[exit]");
+ }
+ }
+}
+
diff -Nru swftools-0.9.2+ds1/lib/as3/ok/defaultparamvalue.as swftools-0.9.1/lib/as3/ok/defaultparamvalue.as
--- swftools-0.9.2+ds1/lib/as3/ok/defaultparamvalue.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/ok/defaultparamvalue.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,57 @@
+package {
+ import flash.display.MovieClip
+ public class Main extends flash.display.MovieClip {
+
+ public function testuint(x:uint=33) {
+ if(x == 33) trace("ok 5/12");
+ }
+ public function testint(x:int=-33) {
+ if(x == -33) trace("ok 6/12");
+ }
+ public function teststring(x:String="33") {
+ if(x == "33") trace("ok 7/12");
+ }
+ public function testfloat(x:Number=33.33) {
+ if(x == 33.33) trace("ok 8/12");
+ }
+ public function testtrue(x:Boolean=true) {
+ if(x == true) trace("ok 9/12");
+ }
+ public function testfalse(x:Boolean=false) {
+ if(x == false) trace("ok 10/12");
+ }
+ public function testnull(x:Object=null) {
+ if(x == null) trace("ok 11/12");
+ }
+ public function testfloat2(x:Number=33) {
+ if(x == 33.0) trace("ok 12/12");
+ }
+
+ public function myfunction(x:String="ok 2/12")
+ {
+ trace(x);
+ }
+ public function myfunction2(i:int,x:String="ok 4/12")
+ {
+ trace(x);
+ }
+
+ public function Main() {
+ myfunction("ok 1/12");
+ myfunction();
+ myfunction2(0,"ok 3/12");
+ myfunction2(0);
+
+ testuint();
+ testint();
+ teststring();
+ testfloat();
+ testtrue();
+ testfalse();
+ testnull();
+ testfloat2();
+
+ trace("[exit]");
+ }
+ }
+}
diff -Nru swftools-0.9.2+ds1/lib/as3/ok/defaultvalue.as swftools-0.9.1/lib/as3/ok/defaultvalue.as
--- swftools-0.9.2+ds1/lib/as3/ok/defaultvalue.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/ok/defaultvalue.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,41 @@
+package {
+ import flash.display.MovieClip
+ public class Main extends flash.display.MovieClip {
+
+ var o; //undefined
+ var s:String; //null
+ var b:Boolean; //false
+ var i:int; //0
+ var u:uint; //0
+ var f:Number; //NaN
+ var m:Main; //null
+
+ public function Main() {
+ var o; //undefined
+ var s:String; //null
+ var b:Boolean; //false
+ var i:int; //0
+ var u:uint; //0
+ var f:Number; //NaN
+ var m:Main; //null
+
+ if(String(o)=="undefined") trace("ok 1/14");
+ if(s===null) trace("ok 2/14");
+ if(b===false) trace("ok 3/14");
+ if(i==0) trace("ok 4/14");
+ if(u==0) trace("ok 5/14");
+ if(String(f)=="NaN") trace("ok 6/14");
+ if(m===null) trace("ok 7/14");
+
+ if(String(this.o)=="undefined") trace("ok 8/14");
+ if(this.s===null) trace("ok 9/14");
+ if(this.b===false) trace("ok 10/14");
+ if(this.i==0) trace("ok 11/14");
+ if(this.u==0) trace("ok 12/14");
+ if(String(this.f)=="NaN") trace("ok 13/14");
+ if(this.m===null) trace("ok 14/14");
+
+ trace("[exit]");
+ }
+ }
+}
diff -Nru swftools-0.9.2+ds1/lib/as3/ok/delete.as swftools-0.9.1/lib/as3/ok/delete.as
--- swftools-0.9.2+ds1/lib/as3/ok/delete.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/ok/delete.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,26 @@
+package {
+ import flash.display.MovieClip
+
+ class C {
+ }
+ public dynamic class Main extends flash.display.MovieClip {
+ function Main() {
+ this.xx = new C;
+ if(this.xx is C) trace("ok 1/2");
+ delete this.xx;
+ if(this.xx is C) trace("error");
+
+ var a:Array = [1,2,3,4];
+ delete a[2];
+ if(a[0]==1 &&
+ a[1]==2 &&
+ String(a[2])=="undefined" &&
+ a[3]==4) trace("ok 2/2");
+
+ //TODO: we can also delete from XML
+
+ trace("[exit]");
+ }
+ }
+}
+
diff -Nru swftools-0.9.2+ds1/lib/as3/ok/dynamicobj.as swftools-0.9.1/lib/as3/ok/dynamicobj.as
--- swftools-0.9.2+ds1/lib/as3/ok/dynamicobj.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/ok/dynamicobj.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,36 @@
+
+package {
+ import flash.display.MovieClip
+ public class Main extends flash.display.MovieClip {
+
+ function test_empty_curlies() {
+ var y:Object = {};
+ if(true) {}
+ {}
+ }
+
+ function Main() {
+ var x:Object =
+ {"one": 1,
+ "two": 2,
+ "three": 3
+ };
+
+ if(x["two"]==2) trace("ok 1/3");
+
+ x.f = function() {trace("ok 2/3")};
+ x.f();
+
+ var str:String = "key";
+ var y:Object = {str:{}};
+
+ var z:Object =
+ {one: 1,two: 2,three: 3};
+
+ if(z.two == 2) trace("ok 3/3");
+
+ trace("[exit]");
+ }
+ }
+}
+
diff -Nru swftools-0.9.2+ds1/lib/as3/ok/elseif.as swftools-0.9.1/lib/as3/ok/elseif.as
--- swftools-0.9.2+ds1/lib/as3/ok/elseif.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/ok/elseif.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,16 @@
+package {
+ import flash.display.MovieClip;
+ public class Main extends flash.display.MovieClip {
+ function Main() {
+ if(false) {
+ trace("error");
+ } else if(true) {
+ trace("ok 1/1");
+ } else {
+ trace("error");
+ }
+
+ trace("[exit]");
+ }
+ }
+}
diff -Nru swftools-0.9.2+ds1/lib/as3/ok/extendclass.as swftools-0.9.1/lib/as3/ok/extendclass.as
--- swftools-0.9.2+ds1/lib/as3/ok/extendclass.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/ok/extendclass.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,18 @@
+
+package {
+
+ import flash.display.MovieClip
+
+ public class Main extends flash.display.MovieClip {
+ public function Main() {
+ if(!(this instanceof ExtendMain)) {
+ var p = new ExtendMain();
+ if(p instanceof ExtendMain) trace("ok");
+ }
+ trace("[exit]");
+ }
+ }
+
+ public class ExtendMain extends Main {
+ }
+}
diff -Nru swftools-0.9.2+ds1/lib/as3/ok/extendinterface.as swftools-0.9.1/lib/as3/ok/extendinterface.as
--- swftools-0.9.2+ds1/lib/as3/ok/extendinterface.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/ok/extendinterface.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,27 @@
+package {
+ import flash.display.MovieClip
+ public interface I1 {
+ function f()
+ }
+ public interface I2 extends I1 {
+ function g()
+ }
+ public class C implements I2 {
+ public function f() {
+ trace("ok 1/2");
+ }
+ public function g() {
+ trace("ok 2/2");
+ }
+ }
+
+ public class Main extends flash.display.MovieClip {
+ function Main() {
+ var x:I2 = new C;
+ x.f();
+ x.g();
+
+ trace("[exit]");
+ }
+ }
+}
diff -Nru swftools-0.9.2+ds1/lib/as3/ok/extends.as swftools-0.9.1/lib/as3/ok/extends.as
--- swftools-0.9.2+ds1/lib/as3/ok/extends.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/ok/extends.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,40 @@
+package p {
+ internal class C {
+ private function e() {
+ trace("err");
+ }
+ protected function f() {
+ trace("ok 1/5");
+ }
+ }
+ public class D extends C {
+ protected function e() {
+ }
+ override protected function f() {
+ super.f()
+ }
+ }
+}
+package {
+ public class X extends p.D {
+ function X() {
+ super.e();
+ f()
+ }
+ }
+ import flash.display.MovieClip
+ public class Main extends flash.display.MovieClip {
+ function Main() {
+ var x = new X
+
+ import p.D
+ /* not sure what the difference between "is" and "instanceof" actually is */
+ if(x is X) trace("ok 2/5");
+ if(x is D) trace("ok 3/5");
+ if(x instanceof X) trace("ok 4/5");
+ if(x instanceof D) trace("ok 5/5");
+
+ trace("[exit]");
+ }
+ }
+}
diff -Nru swftools-0.9.2+ds1/lib/as3/ok/extraparams.as swftools-0.9.1/lib/as3/ok/extraparams.as
--- swftools-0.9.2+ds1/lib/as3/ok/extraparams.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/ok/extraparams.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,24 @@
+package {
+ import flash.display.MovieClip;
+
+ public class Main extends flash.display.MovieClip {
+ public function test2(s,...numbers) {
+ }
+ public function test(s,...numbers) {
+
+ //test2(s,...numbers);
+
+ if(s=="ok")
+ trace("ok 1/3");
+ if(numbers[0]==1 &&
+ numbers[1]==2 &&
+ numbers[2]==3 &&
+ numbers[3]==4) trace("ok 2/3");
+ if(numbers.length==4) trace("ok 3/3");
+ }
+ function Main() {
+ test("ok", 1,2,3,4);
+ trace("[exit]");
+ }
+ }
+}
diff -Nru swftools-0.9.2+ds1/lib/as3/ok/finally2.as swftools-0.9.1/lib/as3/ok/finally2.as
--- swftools-0.9.2+ds1/lib/as3/ok/finally2.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/ok/finally2.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,167 @@
+/* same as finally.as, only for larger finally blocks which require a
+ lookupswitch */
+
+package {
+ import flash.display.MovieClip;
+
+ public class Main extends flash.display.MovieClip {
+ var i=0;
+ function test_return():int {
+ try {
+ if(i==0) return 0;
+ if(i==1) return 2;
+ if(i==2) return 4;
+ if(i==3) return 7;
+ if(i==4) return 9;
+ trace("error");
+ } finally {
+ i = 0;
+ trace("ok","1/11");
+ }
+ trace("error");
+ return 0;
+ }
+
+ function test_break() {
+ do {
+ try {
+ if(i==0) break;
+ trace("error");
+ if(i==3) break;
+ if(i==7) break;
+ if(i==9) break;
+ if(i==11) break;
+ trace("error");
+ } finally {
+ i = 0;
+ trace("ok","2/11");
+ }
+ trace("error");
+ } while(true);
+ }
+
+ function test_fallthrough() {
+ try {
+ var x = 1+1;
+ if(i==1) return;
+ if(i==2) return;
+ if(i==3) return;
+ if(i==4) return;
+ if(i==5) return;
+ } finally {
+ i = 0;
+ trace("ok","3/11");
+ }
+ }
+
+ function test_exception() {
+ try {
+ try {
+ if(i==0)
+ throw new Error();
+ if(i==1)
+ return;
+ if(i==2)
+ return;
+ if(i==3)
+ throw new Object();
+ trace("error");
+ } finally {
+ i = 0;
+ trace("ok","4/11");
+ }
+ trace("error");
+ } catch(e:Error) {
+ i = 0;
+ trace("ok","5/11");
+ }
+ }
+
+ function test_exception2() {
+ var x:int = 0;
+ try {
+ if(i==1)
+ return;
+ if(i==0)
+ throw new Error();
+ if(i==3)
+ throw new Error();
+ trace("error");
+ } catch(e:Error) {
+ x=1;
+ } finally {
+ new Array(1,2,3,4,5,6);
+ i = 0;
+ x*=2;
+ }
+ if(x==2)
+ trace("ok 6/11");
+ }
+
+ function fail1() {
+ try {
+ if(i==0) throw new Error();
+ if(i==7) throw new Error();
+ if(i==11) throw new Error();
+ if(i==15) throw new Error();
+ if(i==17) throw new Error();
+ } finally {
+ new Array(1,2,3,4,5,6);
+ i = 0;
+ trace("ok","7/11");
+ }
+ }
+
+ function fail2() {
+ try {
+ fail1();
+ } finally {
+ new Array(1,2,3,4,5,6);
+ i = 0;
+ trace("ok","8/11");
+ }
+ }
+
+ function test_exception3() {
+ try {
+ fail2();
+ } catch(e:Error) {
+ trace("ok 9/11");
+ }
+ }
+
+ function test_empty() {
+ try {
+ } finally {
+ }
+ trace("ok 10/11");
+ }
+
+ function test_mixed():int {
+ while(true) {
+ try {
+ if(i==3) continue;
+ if(i==2) throw new Error();
+ if(i==1) return 1;
+ if(i==0) break;
+ } finally {
+ trace("ok","11/11");
+ i = 0;
+ }
+ }
+ return 0;
+ }
+
+ function Main() {
+ test_return();
+ test_break();
+ test_fallthrough();
+ test_exception();
+ test_exception2();
+ test_exception3();
+ test_empty();
+ test_mixed();
+ trace("[exit]");
+ }
+ }
+}
diff -Nru swftools-0.9.2+ds1/lib/as3/ok/finally.as swftools-0.9.1/lib/as3/ok/finally.as
--- swftools-0.9.2+ds1/lib/as3/ok/finally.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/ok/finally.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,97 @@
+package {
+ import flash.display.MovieClip;
+
+ public class Main extends flash.display.MovieClip {
+ function test_return() {
+ try {
+ return;
+ trace("error");
+ } finally {
+ trace("ok 1/9");
+ }
+ trace("error");
+ }
+
+ function test_break() {
+ do {
+ try {
+ break;
+ trace("error");
+ } finally {
+ trace("ok 2/9");
+ }
+ trace("error");
+ } while(true);
+ }
+
+ function test_fallthrough() {
+ try {
+ var x = 1+1;
+ } finally {
+ trace("ok 3/9");
+ }
+ }
+
+ function test_exception() {
+ try {
+ try {
+ throw new Error();
+ trace("error");
+ } finally {
+ trace("ok 4/9");
+ }
+ trace("error");
+ } catch(e:Error) {
+ trace("ok 5/9");
+ }
+ }
+
+ function test_exception2() {
+ var x:int = 0;
+ try {
+ throw new Error();
+ trace("error");
+ } catch(e:Error) {
+ x=1;
+ } finally {
+ x++;
+ }
+ if(x==2)
+ trace("ok 6/9");
+ }
+
+ function fail1() {
+ try {
+ throw new Error();
+ } finally {
+ trace("ok 7/9");
+ }
+ }
+
+ function fail2() {
+ try {
+ fail1();
+ } finally {
+ trace("ok 8/9");
+ }
+ }
+
+ function test_exception3() {
+ try {
+ fail2();
+ } catch(e:Error) {
+ trace("ok 9/9");
+ }
+ }
+
+ function Main() {
+ test_return();
+ test_break();
+ test_fallthrough();
+ test_exception();
+ test_exception2();
+ test_exception3();
+ trace("[exit]");
+ }
+ }
+}
diff -Nru swftools-0.9.2+ds1/lib/as3/ok/float.as swftools-0.9.1/lib/as3/ok/float.as
--- swftools-0.9.2+ds1/lib/as3/ok/float.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/ok/float.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,25 @@
+package {
+ import flash.display.MovieClip
+ public class Main extends flash.display.MovieClip {
+ function Main() {
+ /* test normal floats */
+ var x = .25;
+ if(x is Number) trace("ok 1/8");
+ if(x*4==1.0) trace("ok 2/8");
+ var y = -.25;
+ if(y is Number) trace("ok 3/8");
+ if(y*4==-1.0) trace("ok 4/8");
+
+ /* test hex floats */
+ var a = 0x.
+ var b = 0xa.
+ var c = 0x.4
+ var d = 0xa.a
+ if(a==0) trace("ok 5/8");
+ if(b==10.0) trace("ok 6/8");
+ if(c==0.25) trace("ok 7/8");
+ if(d==10.625) trace("ok 8/8");
+ trace("[exit]");
+ }
+ }
+}
diff -Nru swftools-0.9.2+ds1/lib/as3/ok/for2.as swftools-0.9.1/lib/as3/ok/for2.as
--- swftools-0.9.2+ds1/lib/as3/ok/for2.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/ok/for2.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,24 @@
+package {
+ import flash.display.MovieClip
+ public class Main extends flash.display.MovieClip {
+ function Main() {
+ var x:int = 0, y:int = 0;
+
+ for(x=0,y=0;x<10;x++,y++) {
+ }
+ if(y==10) trace("ok 1/2");
+ else trace("error");
+
+ y = 0;
+
+ var o,z:uint = 0;
+ for(x++,y++;x<20;x++,y++) {
+ z++;
+ }
+ if(z==9) trace("ok 2/2");
+ else trace("error");
+ trace("[exit]");
+ }
+ }
+}
+
diff -Nru swftools-0.9.2+ds1/lib/as3/ok/for.as swftools-0.9.1/lib/as3/ok/for.as
--- swftools-0.9.2+ds1/lib/as3/ok/for.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/ok/for.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,29 @@
+
+package {
+ import flash.display.MovieClip
+ public class Main extends flash.display.MovieClip {
+ function Main() {
+ var a1 = 0;
+ for(a1=0;a1<100;a1++) {
+ }
+ if(a1==100) trace("ok 1/4");
+ else trace("error");
+
+ var a3:int;
+ for(a3=0;a3<100;a3++) {
+ a1++;
+ }
+ if(a1==200) trace("ok 2/4");
+ else trace("error");
+
+ if(a3==100) trace("ok 3/4");
+ else trace("error");
+
+ for(var a2=0;a2<99;a2++) {
+ if(a2==80) trace("ok 4/4");
+ }
+ trace("[exit]");
+ }
+ }
+}
+
diff -Nru swftools-0.9.2+ds1/lib/as3/ok/for-in.as swftools-0.9.1/lib/as3/ok/for-in.as
--- swftools-0.9.2+ds1/lib/as3/ok/for-in.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/ok/for-in.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,56 @@
+package {
+ import flash.display.MovieClip
+ public class Main extends flash.display.MovieClip {
+
+ var ci:int = 0;
+
+ function Main() {
+ var a:Array = new Array(1,2,3,4,6,5,7,8,9,10);
+ var j:int = 0;
+ for(var x in a) {
+ j += x;
+ }
+ if(j==45) trace("ok 1/6");
+
+ var y;
+ j = 0;
+ for(y in a) {
+ j += y;
+ }
+ if(j==45) trace("ok 2/6");
+
+ j = 0;
+ for each(var x in a) {
+ j += x;
+ }
+ if(j==55) trace("ok 3/6");
+
+ var z = 0;
+ j = 0;
+ for each(z in a) {
+ j += z;
+ }
+ if(j==55) trace("ok 4/6");
+
+ var i:int = 0;
+ j = 0;
+ for each(i in a) {
+ j += i;
+ if(i==6)
+ break;
+ else
+ continue;
+ }
+ if(j==16) trace("ok 5/6");
+
+ j = 0;
+ for each(ci in a) {
+ j += ci;
+ }
+ if(j == 55) trace("ok 6/6");
+
+ trace("[exit]");
+ }
+ }
+}
+
diff -Nru swftools-0.9.2+ds1/lib/as3/ok/forward2.as swftools-0.9.1/lib/as3/ok/forward2.as
--- swftools-0.9.2+ds1/lib/as3/ok/forward2.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/ok/forward2.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,51 @@
+package {
+ import flash.events.Event;
+ import flash.display.MovieClip
+
+ public class Main extends flash.display.MovieClip
+ {
+ public function test1(e:Event=null)
+ {
+ try {
+ var a:Array = new Array
+ throw new Error();
+ } catch (e:Error) {
+ if(e instanceof Error)
+ trace("ok 1/4");
+ }
+ var b = a[0]; // to trigger forward variable resolving
+ }
+ public function test2()
+ {
+ var e:Event;
+ try {
+ var a:Array = new Array
+ throw new Error();
+ } catch (e:Error) {
+ if(e instanceof Error)
+ trace("ok 2/4");
+ }
+ var b = a[0]; // to trigger forward variable resolving
+ }
+
+ public function test3()
+ {
+ if(x == null)
+ trace("ok 3/4");
+
+ var x:Error;
+ try {
+ if(true) throw new Error();
+ } catch (x:Error) {
+ trace("ok 4/4");
+ }
+ }
+
+ public function Main() {
+ test1();
+ test2();
+ test3();
+ trace("[exit]");
+ }
+ }
+}
diff -Nru swftools-0.9.2+ds1/lib/as3/ok/forward3.as swftools-0.9.1/lib/as3/ok/forward3.as
--- swftools-0.9.2+ds1/lib/as3/ok/forward3.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/ok/forward3.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,18 @@
+package {
+ import flash.events.Event;
+ import flash.display.MovieClip
+
+ public class Main extends flash.display.MovieClip
+ {
+ var vars = ["ok 1/2","ok 2/2"];
+ public function Main()
+ {
+ for (var p:String in this.vars) {
+ if(int(p)==0) trace(vars[p]);
+ }
+ for (p in this.vars) {
+ if(int(p)==1) trace(vars[p]);
+ }
+ }
+ }
+}
diff -Nru swftools-0.9.2+ds1/lib/as3/ok/forward.as swftools-0.9.1/lib/as3/ok/forward.as
--- swftools-0.9.2+ds1/lib/as3/ok/forward.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/ok/forward.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,14 @@
+package {
+ import flash.display.MovieClip
+ public class Main extends flash.display.MovieClip
+ {
+ public function Main():void
+ {
+ if(ok==null) trace("ok 1/2");
+ var ok:String = "foo";
+ if(ok=="foo") trace("ok 2/2");
+ trace("[exit]");
+ }
+ }
+}
+
diff -Nru swftools-0.9.2+ds1/lib/as3/ok/forward_inner.as swftools-0.9.1/lib/as3/ok/forward_inner.as
--- swftools-0.9.2+ds1/lib/as3/ok/forward_inner.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/ok/forward_inner.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,26 @@
+package {
+ import flash.events.Event;
+ import flash.display.MovieClip
+
+ public class Main extends flash.display.MovieClip
+ {
+ public function test(s:String, f)
+ {
+ if(f!=null)
+ trace("ok 2/3");
+ f(null);
+ }
+
+ public function Main()
+ {
+ if(typeof(x) == "number")
+ trace("ok 1/3");
+
+ test( "resize", function (e:Event):void {
+ trace("ok 3/3");
+ });
+
+ var x:int = 3;
+ }
+ }
+}
diff -Nru swftools-0.9.2+ds1/lib/as3/ok/funcassign.as swftools-0.9.1/lib/as3/ok/funcassign.as
--- swftools-0.9.2+ds1/lib/as3/ok/funcassign.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/ok/funcassign.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,31 @@
+package {
+ import flash.display.MovieClip;
+ public class Main extends flash.display.MovieClip {
+
+ function ok1() {
+ trace("ok 1/3");
+ }
+ function ok2(a:uint) {
+ if(a==2)
+ trace("ok 2/3");
+ }
+ function ok3():Boolean {
+ trace("ok 3/3");
+ return true;
+ }
+
+ var a;
+ var b:Function;
+ var c;
+
+ function Main() {
+ this.a = ok1;
+ this.a();
+ this.b = ok2;
+ this.b(2);
+ this.c = ok3;
+ if(!this.c()) trace("error");
+ trace("[exit]");
+ }
+ }
+}
diff -Nru swftools-0.9.2+ds1/lib/as3/ok/getset2.as swftools-0.9.1/lib/as3/ok/getset2.as
--- swftools-0.9.2+ds1/lib/as3/ok/getset2.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/ok/getset2.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,17 @@
+
+package {
+ import flash.display.MovieClip;
+
+ public class Main extends flash.display.MovieClip {
+ public static function set foobar(val:String ):void {
+ }
+ public static function get foobar():String
+ {
+ return "ok";
+ }
+ function Main() {
+ trace(Main.foobar);
+ trace("[exit]");
+ }
+ }
+}
diff -Nru swftools-0.9.2+ds1/lib/as3/ok/getset.as swftools-0.9.1/lib/as3/ok/getset.as
--- swftools-0.9.2+ds1/lib/as3/ok/getset.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/ok/getset.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,29 @@
+package package2 {
+ public class Test {
+ public function set x (v) {
+ if(v==2)
+ trace("ok 2/2");
+ }
+ public function get x ():uint {
+ trace("ok 1/2");
+ return 1;
+ }
+
+ public function set n(n:uint) {
+ }
+ }
+}
+
+package {
+ import flash.display.MovieClip;
+ import package2.Test
+
+ public class Main extends flash.display.MovieClip {
+ function Main() {
+ var t:Test = new Test();
+ t.x++;
+ t.n = 3;
+ trace("[exit]");
+ }
+ }
+}
diff -Nru swftools-0.9.2+ds1/lib/as3/ok/globalfunction.as swftools-0.9.1/lib/as3/ok/globalfunction.as
--- swftools-0.9.2+ds1/lib/as3/ok/globalfunction.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/ok/globalfunction.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,39 @@
+package package_A {
+
+ import flash.utils.setInterval;
+
+ internal class class_A {
+
+ function class_A() {
+ trace("ok 2/4")
+ }
+ internal function f() {
+ trace("ok 3/4");
+ }
+ static internal function g() {
+ trace("ok 4/4");
+ }
+ }
+
+ internal function i_A() {
+ trace("ok 1/4");
+ (new class_A).f()
+ }
+
+ public function p_A() {
+ i_A();
+ class_A.g()
+ }
+}
+
+package {
+ import flash.display.MovieClip
+ import package_A.p_A
+
+ public class Main extends flash.display.MovieClip {
+ public function Main() {
+ p_A()
+ trace("[exit]");
+ }
+ }
+}
diff -Nru swftools-0.9.2+ds1/lib/as3/ok/globalvarassign.as swftools-0.9.1/lib/as3/ok/globalvarassign.as
--- swftools-0.9.2+ds1/lib/as3/ok/globalvarassign.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/ok/globalvarassign.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,17 @@
+package {
+
+ public var mystring:String;
+ public function run():void
+ {
+ mystring = "test";
+ trace('ok');
+ }
+
+ import flash.display.MovieClip
+ public class Main extends flash.display.MovieClip {
+ public function Main () {
+ run();
+ trace("[exit]");
+ }
+ }
+}
diff -Nru swftools-0.9.2+ds1/lib/as3/ok/hide.as swftools-0.9.1/lib/as3/ok/hide.as
--- swftools-0.9.2+ds1/lib/as3/ok/hide.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/ok/hide.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,28 @@
+
+package {
+ var xx = "error";
+
+ function print_xx()
+ {
+ trace(xx);
+ }
+
+ import flash.display.MovieClip;
+ public class Main extends flash.display.MovieClip {
+
+ public var xx = "error";
+
+ public static function f()
+ {
+ // this sets the *package* variable x,
+ // *not* the class variable (which is unreachable from here)
+ xx = "ok 1/1";
+ }
+
+ public function Main() {
+ f(); // run static function
+ print_xx();
+ trace("[exit]");
+ }
+ }
+}
diff -Nru swftools-0.9.2+ds1/lib/as3/ok/if.as swftools-0.9.1/lib/as3/ok/if.as
--- swftools-0.9.2+ds1/lib/as3/ok/if.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/ok/if.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,28 @@
+package {
+ import flash.display.MovieClip;
+ public class Main extends flash.display.MovieClip {
+ function Main() {
+ if(true) trace("ok 1/5");
+ if(false) trace("error");
+ if(1+1==2) trace("ok 2/5");
+ if(1+1==3) trace("error");
+ if(1+1!=2) trace("error");
+ if(1+2==3) trace("ok 3/5");
+
+ if(1+1==3) {} else {trace("ok 4/5");}
+
+ if(false) trace("error");
+ else if(false) trace("error");
+ else if(true) trace("ok 5/5");
+ else if(false) trace("error");
+
+ if(true) {
+ var x;
+ } else {
+ var x;
+ }
+
+ trace("[exit]");
+ }
+ }
+}
diff -Nru swftools-0.9.2+ds1/lib/as3/ok/import.as swftools-0.9.1/lib/as3/ok/import.as
--- swftools-0.9.2+ds1/lib/as3/ok/import.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/ok/import.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,30 @@
+package package1 {
+ public class Class1 {
+ public function Class1() {
+ trace("ok 1/3");
+ }
+ }
+}
+package package2 {
+ public class Class2 {
+ public function Class2() {
+ trace("ok 2/3");
+ }
+ }
+}
+
+package {
+ import package1.Class1
+ import package2.*
+ import flash.events.TextEvent
+
+ public class Main extends flash.display.MovieClip {
+ public function Main() {
+ new Class1();
+ new Class2();
+ var t = new TextEvent("type",true,true,"ok 3/3");
+ trace(t.text);
+ trace("[exit]");
+ }
+ }
+}
diff -Nru swftools-0.9.2+ds1/lib/as3/ok/in.as swftools-0.9.1/lib/as3/ok/in.as
--- swftools-0.9.2+ds1/lib/as3/ok/in.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/ok/in.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,41 @@
+package {
+ import flash.display.MovieClip;
+
+ public class C {
+ public var x;
+ public function y() {};
+ var e1;
+ function e2() {};
+
+ public static var s1;
+ public static function s2() {}
+ }
+ public class Main extends flash.display.MovieClip {
+ function Main() {
+ /* test "in" for arrays */
+ var a:Array = new Array(1,2,3,4);
+ if(3 in a) trace("ok 1/7");
+ if(5 in a) trace("error");
+ else trace("ok 2/7");
+
+ /* test "in" for normal classes */
+ var c:C = new C;
+ if("x" in c) trace("ok 3/7");
+ if("y" in c) trace("ok 4/7");
+ if("e1" in c) trace("error"); // not public
+ if("e2" in c) trace("error"); // not public
+
+ /* test "in" for static members */
+ if("s1" in C) trace("ok 5/7");
+ if("s2" in C) trace("ok 6/7");
+
+ /* test "in" for dynamic objects */
+ var o:Object = new Object();
+ o["r"] = 1;
+ if("r" in o) trace("ok 7/7");
+ delete o["r"];
+ if("r" in o) trace("error");
+ trace("[exit]");
+ }
+ }
+}
diff -Nru swftools-0.9.2+ds1/lib/as3/ok/innerfunction.as swftools-0.9.1/lib/as3/ok/innerfunction.as
--- swftools-0.9.2+ds1/lib/as3/ok/innerfunction.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/ok/innerfunction.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,48 @@
+package {
+ import flash.display.MovieClip
+ import flash.events.Event
+
+ public class Main extends flash.display.MovieClip {
+
+ public function test1(y:int, ...rest)
+ {
+ var a:Array = [null];
+ a[0] = function() {
+ y = y + 1;
+ }
+ a[0]();
+ a[0]();
+ if(y!=2) trace("error")
+ else trace("ok 1/3");
+ }
+ public function test2(y:uint)
+ {
+ var inc_y = function() {
+ y = y + 1;
+ }
+
+ inc_y();
+ inc_y();
+
+ if(y!=2) trace("error")
+ else trace("ok 2/3");
+ }
+
+ var msg:String = "ok 3/3";
+ public function test3(y:int)
+ {
+ var f = function() {
+ trace(msg);
+ }
+ f();
+ }
+
+ public function Main()
+ {
+ this.test1(0,5)
+ this.test2(0)
+ this.test3(0)
+ trace("[exit]");
+ }
+ }
+}
diff -Nru swftools-0.9.2+ds1/lib/as3/ok/innerfunctionlate.as swftools-0.9.1/lib/as3/ok/innerfunctionlate.as
--- swftools-0.9.2+ds1/lib/as3/ok/innerfunctionlate.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/ok/innerfunctionlate.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,34 @@
+package {
+ import flash.display.MovieClip
+ import flash.events.Event
+
+ public class Main extends flash.display.MovieClip {
+ public function Main() {
+ var log = f3;
+ f1("ok 1/3");
+ var f = f2;
+ f("2/3");
+
+ f0();
+
+ function f0() {
+ f3("ok","3","3");
+ }
+ function f1(text) {
+ trace(text);
+ }
+ function f2(text) {
+ trace("ok "+text);
+ }
+ function f3(t1,t2,t3) {
+ trace(t1+" "+t2+"/"+t3);
+ }
+
+ var f4 = function(e:Event) {
+ trace(e.type);
+ }
+
+ trace("[exit]");
+ }
+ }
+}
diff -Nru swftools-0.9.2+ds1/lib/as3/ok/innerfunctionnest.as swftools-0.9.1/lib/as3/ok/innerfunctionnest.as
--- swftools-0.9.2+ds1/lib/as3/ok/innerfunctionnest.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/ok/innerfunctionnest.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,35 @@
+package {
+ import flash.display.MovieClip
+ import flash.events.Event
+
+ public class Main extends flash.display.MovieClip {
+ public function Main() {
+ var x:int=0;
+ var f1ok:Boolean = false;
+ var f2ok:Boolean = false;
+ var f3ok:Boolean = false;
+ f1(1);
+ function f1(level:int) {
+ var y:int = 0;
+ f2(level+1);
+ x = y;
+ f1ok = true;
+ function f2(level:int) {
+ var z:int = 0;
+ f3(level+1);
+ y = z;
+ f2ok = true;
+ function f3(level:int) {
+ if(level==3)
+ trace("ok");
+ z = 4;
+ f3ok = true;
+ }
+ }
+ }
+ if(x!=4 || !f1ok || !f2ok || !f3ok)
+ trace("error");
+ trace("[exit]");
+ }
+ }
+}
diff -Nru swftools-0.9.2+ds1/lib/as3/ok/innerfunctionslots.as swftools-0.9.1/lib/as3/ok/innerfunctionslots.as
--- swftools-0.9.2+ds1/lib/as3/ok/innerfunctionslots.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/ok/innerfunctionslots.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,22 @@
+package {
+ import flash.display.MovieClip
+ import flash.events.Event
+
+ public class Main extends flash.display.MovieClip {
+ public function test(e:Event) {
+
+ if(e.type instanceof String) {
+ trace("ok");
+ }
+
+ function inner(x:String) {
+ trace(e.type);
+ }
+ }
+ public function Main() {
+ var e = new Event("");
+ test(e);
+ trace("[exit]");
+ }
+ }
+}
diff -Nru swftools-0.9.2+ds1/lib/as3/ok/innerrecurse.as swftools-0.9.1/lib/as3/ok/innerrecurse.as
--- swftools-0.9.2+ds1/lib/as3/ok/innerrecurse.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/ok/innerrecurse.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,21 @@
+package {
+ import flash.display.MovieClip
+
+ public class Main extends flash.display.MovieClip {
+ public function Main() {
+ var i = 0;
+ f(0);
+ function f(j:int) {
+ if(i!=j)
+ trace("error");
+ i++;
+ if(j==3) {
+ trace("ok");
+ return;
+ }
+ f(j+1);
+ }
+ trace("[exit]");
+ }
+ }
+}
diff -Nru swftools-0.9.2+ds1/lib/as3/ok/interface.as swftools-0.9.1/lib/as3/ok/interface.as
--- swftools-0.9.2+ds1/lib/as3/ok/interface.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/ok/interface.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,22 @@
+package {
+ import flash.display.MovieClip
+ import flash.utils.ByteArray
+ public interface I1 {
+ function f()
+ }
+ public class TestI1 implements I1{
+ public function f() {
+ trace("ok");
+ }
+ }
+ public class Main extends flash.display.MovieClip {
+ function Main() {
+ var x:I1 = new TestI1();
+ x.f();
+ trace("[exit]");
+ }
+ }
+ public interface I2 {
+ function init(key:ByteArray):void;
+ }
+}
diff -Nru swftools-0.9.2+ds1/lib/as3/ok/late.as swftools-0.9.1/lib/as3/ok/late.as
--- swftools-0.9.2+ds1/lib/as3/ok/late.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/ok/late.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,24 @@
+package {
+ import flash.display.MovieClip
+ public class Main extends flash.display.MovieClip {
+ function Main() {
+ message1 = "ok 1/2";
+ this.message2 = "ok 2/2";
+ printok1();
+ trace("[exit]");
+ }
+ public function printok1() {
+ printok2(17);
+ }
+ public function printok2(x:uint) {
+ if(x==17)
+ this.printok3();
+ }
+ public function printok3() {
+ trace(message1);
+ trace(this.message2);
+ }
+ internal var message1:String = "error";
+ internal var message2:String = "error";
+ }
+}
diff -Nru swftools-0.9.2+ds1/lib/as3/ok/members.as swftools-0.9.1/lib/as3/ok/members.as
--- swftools-0.9.2+ds1/lib/as3/ok/members.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/ok/members.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,42 @@
+package package1 {
+ public class Class1 {
+ public var a;
+ public var b:int;
+ public var c:int;
+ public var d = 1;
+ public var e:int = 1;
+
+ function Class1() {
+ }
+ public function write() {
+ if(a==1)
+ trace("ok 1/5");
+ if(b==1)
+ trace("ok 2/5");
+ if(c==1)
+ trace("ok 3/5");
+ if(d==1)
+ trace("ok 4/5");
+ if(e==1)
+ trace("ok 5/5");
+ }
+ }
+}
+package {
+ import package1.Class1
+ import flash.display.MovieClip
+
+ public class Main extends flash.display.MovieClip {
+ public function Main() {
+ var cls = new Class1();
+ cls.a = 1;
+ cls.b++;
+ cls.c = cls.a;
+ cls.write();
+
+ cls.c += 1;
+ cls.c -= cls.a;
+ trace("[exit]");
+ }
+ }
+}
diff -Nru swftools-0.9.2+ds1/lib/as3/ok/namespaces1.as swftools-0.9.1/lib/as3/ok/namespaces1.as
--- swftools-0.9.2+ds1/lib/as3/ok/namespaces1.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/ok/namespaces1.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,80 @@
+package my.namespaces {
+ public namespace ns1 = "http://www.some.other/namespace";
+ public namespace ns2 = "http://www.swftools.org/";
+ public namespace ns3 = "http://yet.some.other/namespace";
+ public namespace ns4 = "bla bla";
+
+ public namespace ns5 = "bla bla 2";
+
+ public class Test {
+
+ ns1 static function test() {
+ trace("error");
+ }
+ ns2 static function test() {
+ trace("ok 2/6");
+ use namespace my.namespaces.ns2;
+ (new Test()).test2()
+ }
+ ns3 static function test() {
+ trace("error");
+ }
+
+ ns1 function test2() {trace("error");}
+ ns2 function test2() {trace("ok 3/6");}
+ ns3 function test2() {trace("error");}
+
+ ns4 static function test3() {
+ trace("ok 4/6");
+ }
+
+ ns1 function test4() {trace("ok 5/6");}
+ ns2 function test4() {trace("ok 6/6");}
+ }
+}
+
+package {
+
+ import flash.display.MovieClip
+ import flash.utils.Proxy
+ import flash.utils.flash_proxy
+
+ use namespace flash.utils.flash_proxy;
+
+ public namespace ns4clone = "bla bla";
+ use namespace ns4clone;
+
+ public class Main extends flash.display.MovieClip {
+
+ use namespace my.namespaces.ns2;
+ import my.namespaces.*;
+ use namespace ns5;
+
+ private function test1() {
+ my.namespaces.Test.test()
+ }
+
+ public function Main()
+ {
+ var p:Proxy = new Proxy
+ try {
+ p.hasProperty("test")
+ } catch(e:Error) {
+ // Proxy is similar to an interface, and will throw some kind
+ // of "class not implemented" exception
+ trace("ok 1/6");
+ }
+ my.namespaces.Test.test()
+ my.namespaces.Test.test3()
+
+ use namespace my.namespaces.ns1;
+ use namespace my.namespaces.ns2;
+ var test:Test = new Test();
+ test.ns1::test4();
+ test.ns2::test4();
+
+ trace("[exit]");
+ }
+ }
+}
+
diff -Nru swftools-0.9.2+ds1/lib/as3/ok/namespaces2.as swftools-0.9.1/lib/as3/ok/namespaces2.as
--- swftools-0.9.2+ds1/lib/as3/ok/namespaces2.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/ok/namespaces2.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,39 @@
+package {
+
+ import flash.utils.*;
+ import flash.display.MovieClip;
+
+ use namespace flash_proxy;
+
+
+ dynamic public class OverrideProxy extends Proxy {
+ flash_proxy override function callProperty($name:*, ...$args:Array):* {
+ return null;
+ }
+ }
+
+ var ns2:Namespace = flash_proxy;
+
+ dynamic public class Main extends flash.display.MovieClip {
+
+ flash_proxy function tf(x:int):*
+ {
+ trace("ok "+x+"/3");
+ return null;
+ }
+
+
+ public function Main()
+ {
+ this.tf(1);
+ tf(2);
+ var ns:Namespace = flash_proxy;
+
+ if(ns == ns2)
+ trace("ok 3/3");
+
+ trace("[exit]");
+ }
+
+ }
+}
diff -Nru swftools-0.9.2+ds1/lib/as3/ok/nested_functions.as swftools-0.9.1/lib/as3/ok/nested_functions.as
--- swftools-0.9.2+ds1/lib/as3/ok/nested_functions.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/ok/nested_functions.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,39 @@
+package {
+ import flash.display.MovieClip
+ import flash.geom.Point
+
+ public class Main extends flash.display.MovieClip {
+ static public var ok:String = "ok";
+
+ function test(x,y)
+ {
+ trace("ok 1/5")
+ x = msg(2, 5)
+ y = msg(3, 5)
+ trace(x);
+ trace(y);
+
+ function msg(nr,total):String {
+ return ""+this.Main.ok+" "+nr+"/"+total
+ }
+
+ var x1 = "err";
+ var x2 = "err";
+
+ function setok() {
+ x1 = "ok 4/5";
+ x2 = "ok 5/5";
+ }
+ var s = setok;
+ s();
+ trace(x1);
+ trace(x2);
+
+ trace("[exit]");
+ }
+
+ public function Main() {
+ test(3,4);
+ }
+ }
+}
diff -Nru swftools-0.9.2+ds1/lib/as3/ok/new.as swftools-0.9.1/lib/as3/ok/new.as
--- swftools-0.9.2+ds1/lib/as3/ok/new.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/ok/new.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,75 @@
+package some.other.packag3 {
+ public class Class4 {
+ public function Class4(x=1) {
+ if(x) {
+ trace("ok 4/9");
+ new Class4(0);
+ }
+ }
+ }
+
+ public class Class9 {public function Class9() {trace("ok 9/9");}}
+}
+
+package {
+ public class Class1 {
+ public function Class1() {
+ trace("ok 1/9");
+ }
+ }
+ public class Class2 {
+ public function Class2() {
+ trace("ok 2/9");
+ }
+ }
+ public class Class3 {
+ public function Class3(x,s) {
+ trace(s)
+ }
+ }
+
+ public class Class5 {
+ public function Class5() {
+ trace("ok 5/9")
+ }
+ }
+ public class Class6 {
+ public function Class6() {
+ trace("ok 6/9")
+ }
+ }
+ public class Class7 {
+ public function Class7() {
+ trace("ok 7/9")
+ }
+ }
+ public class ClassX {
+ public function ClassX(x:uint) {
+ trace("ok "+x+"/9")
+ }
+ }
+
+ import flash.display.MovieClip
+ public class Main extends flash.display.MovieClip {
+ public function Main() {
+ new Class1()
+ new Class2
+ new Class3(0,"ok 3/9")
+ import some.other.packag3.Class4
+ new Class4();
+
+ var x = Class5;
+ new x;
+ var y:Class = Class6;
+ new y;
+
+ var a = [Class7, ClassX];
+ new a[0];
+ new a[1](8);
+
+ new some.other.packag3.Class9;
+
+ trace("[exit]");
+ }
+ }
+}
diff -Nru swftools-0.9.2+ds1/lib/as3/ok/nopackage2.as swftools-0.9.1/lib/as3/ok/nopackage2.as
--- swftools-0.9.2+ds1/lib/as3/ok/nopackage2.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/ok/nopackage2.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,12 @@
+import flash.system.Capabilities
+
+trace("ok 1/3");
+if(Capabilities.os is String) {
+ trace("ok 2/3");
+}
+function f()
+{
+ trace("ok 3/3");
+}
+f()
+trace("[exit]");
diff -Nru swftools-0.9.2+ds1/lib/as3/ok/nopackage.as swftools-0.9.1/lib/as3/ok/nopackage.as
--- swftools-0.9.2+ds1/lib/as3/ok/nopackage.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/ok/nopackage.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,23 @@
+/* functions which are valid for this source file only */
+
+function f1() {
+ trace("ok 1/3")
+};
+
+package {
+ import flash.display.MovieClip
+
+ public class Main extends flash.display.MovieClip {
+ public function Main() {
+ f1()
+ trace("ok 2/3")
+ f3()
+ trace("[exit]");
+ }
+ }
+}
+
+function f3() {
+ trace("ok 3/3")
+};
+
diff -Nru swftools-0.9.2+ds1/lib/as3/ok/novalue.as swftools-0.9.1/lib/as3/ok/novalue.as
--- swftools-0.9.2+ds1/lib/as3/ok/novalue.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/ok/novalue.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,45 @@
+package {
+ import flash.display.MovieClip
+
+ public class Main extends flash.display.MovieClip {
+
+ var count:int = 1;
+ var num:int = 6;
+ function assert(b) {
+ if(b) {
+ trace("ok "+count+"/"+num);
+ } else {
+ trace("error "+count+"/"+num);
+ }
+ count = count + 1
+ }
+ function compare(x,y) {
+ assert(x==y);
+ }
+
+ function Main() {
+ var x:int=0;
+ var y:int=0;
+
+ /* test for &&/|| as "inline if" */
+
+ x++;
+ assert(x==1);
+
+ x++ || y++;
+ assert(x==2);
+ assert(y==0);
+
+ x++ && y++;
+ assert(x==3);
+ assert(y==1);
+
+ false && y++;
+ assert(y==1);
+
+ trace("[exit]");
+ }
+
+ }
+}
+
diff -Nru swftools-0.9.2+ds1/lib/as3/ok/null.as swftools-0.9.1/lib/as3/ok/null.as
--- swftools-0.9.2+ds1/lib/as3/ok/null.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/ok/null.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,18 @@
+package {
+
+ public class Main extends flash.display.MovieClip {
+ public function Main() {
+ var x = null;
+ var y = null;
+ if(x == y) {
+ trace("ok 1/2");
+ }
+ if(x === y) {
+ trace("ok 2/2");
+ }
+ trace("[exit]");
+
+ }
+ }
+
+}
diff -Nru swftools-0.9.2+ds1/lib/as3/ok/numbers.as swftools-0.9.1/lib/as3/ok/numbers.as
--- swftools-0.9.2+ds1/lib/as3/ok/numbers.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/ok/numbers.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,43 @@
+package test.package {
+ public class Main extends flash.display.MovieClip {
+ function Main() {
+ /* test the encoding of various constants.
+ Depending on the radix size, int constants may be
+ encoded as byte, u30 short, u31 short, signed, etc. */
+ var a1 = 127;
+ if(String(a1) == "127") trace("ok 1/16");
+ var a2 = 256;
+ if(String(a2) == "256") trace("ok 2/16");
+ var a3 = 1073741823;
+ if(String(a3) == "1073741823") trace("ok 3/16");
+ var a4 = 1073741824;
+ if(String(a4) == "1073741824") trace("ok 4/16");
+ var a5 = 2147483647;
+ if(String(a5) == "2147483647") trace("ok 5/16");
+ var a6 = -1;
+ if(String(a6) == "-1") trace("ok 6/16");
+ var a7 = -127;
+ if(String(a7) == "-127") trace("ok 7/16");
+ var a8 = -32767;
+ if(String(a8) == "-32767") trace("ok 8/16");
+ var a9 = -32768;
+ if(String(a9) == "-32768") trace("ok 9/16");
+ var a10 = -32769;
+ if(String(a10) == "-32769") trace("ok 10/16");
+ var a11 = -65536;
+ if(String(a11) == "-65536") trace("ok 11/16");
+ var a12 = -1073741823;
+ if(String(a12) == "-1073741823") trace("ok 12/16");
+ var a13 = -1073741824;
+ if(String(a13) == "-1073741824") trace("ok 13/16");
+ var a14 = 0xa3b5c7f;
+ if(String(a14) == "171662463") trace("ok 14/16");
+ var a15 = -0xa3b5c7f;
+ if(String(a15) == "-171662463") trace("ok 15/16");
+ var a16 = 1e9;
+ if(String(a16) == "1000000000") trace("ok 16/16");
+ trace("[exit]");
+ }
+ }
+}
+
diff -Nru swftools-0.9.2+ds1/lib/as3/ok/ops.as swftools-0.9.1/lib/as3/ok/ops.as
--- swftools-0.9.2+ds1/lib/as3/ok/ops.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/ok/ops.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,93 @@
+
+package {
+ import flash.display.MovieClip
+ public class Main extends flash.display.MovieClip {
+ var count:int = 1;
+ var num:int = 30;
+ function assert(b:Boolean) {
+ if(b) {
+ trace("ok "+count+"/"+num);
+ } else {
+ trace("error "+count+"/"+num);
+ }
+ count = count + 1
+ }
+ function Main() {
+ /* operations not tested here:
+ * comparison is tested in compare.as
+ * 'as' and 'is' are tested in typecast.as and extends.as
+ * ++ and -- are tested in assignments.as
+ * 'in' is tested by in.as
+ * || and && are tested in boolvalue.as
+ * = is tested in assignments.as
+ * typeof is tested in typeof.as
+ */
+
+ /* test unary minus */
+ assert(-(3) == -3);
+
+ /* test tenary operator */
+ assert((true?1:2) == 1);
+ true?assert(1):assert(0);
+ false?assert(0):assert(1);
+
+ /* test other operators */
+ trace("[arithmetric]");
+ assert(3*3==9);
+ assert(3/3==1);
+ assert(10%4==2);
+ assert(2+3==5);
+ assert(2-3==-1);
+
+ /* test or */
+ var y = 0;
+ var x = y ||Â 1;
+ assert(x);
+ var z = x &&Â 1;
+ assert(z);
+
+ /* test not */
+ trace("[not]");
+ assert(!false);
+
+ /* test strict equals/unequals */
+ trace("[strict equals]");
+ assert(3===3);
+ assert(3!==4);
+ assert(!(3===4));
+ assert(!(3!==3));
+
+ /* test bit operations */
+ trace("[bit operations]");
+ assert(!(0xaaaaaa & 0x555555))
+ assert((0xaa | 0x55) == 0xff);
+ assert((0xff ^ 0x55) == 0xaa);
+ assert((1 & ~1) == 0);
+ assert((1|~1)==~0);
+
+ assert((1|2|4|8|16|32|64|128) == 0xff);
+
+ /* test shift operations */
+ trace("[shift operations]");
+ assert((0xff<<8)==0xff00);
+ assert((0xff>>4)==0x0f);
+ assert((-1>>1)==-1);
+ assert((-1>>1)==-1);
+ assert((-1>>>1)>0);
+
+ /* test void */
+ trace("[void]");
+ var v = void;
+ assert(String(v)=="undefined");
+ v = void 3;
+ assert(String(v)=="undefined");
+
+ /* test comma */
+ trace("[comma]");
+ assert( (1,2,3,4) == 4);
+
+ trace("[exit]");
+ }
+ }
+}
+
diff -Nru swftools-0.9.2+ds1/lib/as3/ok/override_ns.as swftools-0.9.1/lib/as3/ok/override_ns.as
--- swftools-0.9.2+ds1/lib/as3/ok/override_ns.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/ok/override_ns.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,32 @@
+package {
+ import flash.events.*;
+ import flash.utils.*;
+ import flash.display.MovieClip;
+
+ dynamic public class ExtendProxy1 extends Proxy
+ {
+ import flash.utils.flash_proxy;
+ flash_proxy override function callProperty($name:*, ...$args:Array):*
+ {
+ trace("ok 1/2");
+ }
+ }
+ dynamic public class ExtendProxy2 extends Proxy
+ {
+ import flash.utils.*;
+ flash_proxy override function callProperty($name:*, ...$args:Array):*
+ {
+ trace("ok 2/2");
+ }
+ }
+
+ public class Main extends flash.display.MovieClip
+ {
+ public function Main()
+ {
+ new ExtendProxy1().callProperty();
+ new ExtendProxy2().callProperty();
+ trace("[exit]");
+ }
+ }
+}
diff -Nru swftools-0.9.2+ds1/lib/as3/ok/packageinit.as swftools-0.9.1/lib/as3/ok/packageinit.as
--- swftools-0.9.2+ds1/lib/as3/ok/packageinit.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/ok/packageinit.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,36 @@
+var np_x = "ok 4/4";
+
+package some.other.module {
+ public var msg = "ok 2/4";
+
+ public function getmsg() {
+ return "ok 3/4";
+ }
+}
+
+package {
+ import flash.display.MovieClip
+ import flash.system.Capabilities
+ import some.other.module.*
+
+ var mode = 3;
+ var message="error";
+ /* test code which executes directly in a package */
+ if(mode == 3)
+ message = "ok 1/4";
+ else
+ message = "error";
+
+ trace(message);
+
+ /* test access to other classes static fields during our init code */
+ var os;
+ os = Capabilities.os;
+
+ trace(msg);
+ trace(getmsg());
+}
+
+trace(np_x);
+
+trace("[exit]");
diff -Nru swftools-0.9.2+ds1/lib/as3/ok/packagestr.as swftools-0.9.1/lib/as3/ok/packagestr.as
--- swftools-0.9.2+ds1/lib/as3/ok/packagestr.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/ok/packagestr.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,44 @@
+package {
+ import flash.display.MovieClip
+ import flash.utils.*
+
+ public class Main extends flash.display.MovieClip {
+ function Main() {
+ /* static class member, with full path */
+ var x:String = flash.events.DataEvent.DATA;
+ if(x == "data")
+ trace("ok 1/4");
+
+ /* This definition makes the below fail for as3compile, while
+ it still works in Flex.
+ var flash:Object = new Object();
+ flash["events"] = new Object();*/
+
+ import flash.events.DataEvent
+ //trace(flash.events); should fail
+
+ /* class, with full path */
+ var y = new flash.events.DataEvent("");
+ if(y is flash.events.Event)
+ trace("ok 2/4");
+
+ /* package variable, with full path */
+ var z = flash.utils.flash_proxy;
+ if(z is Namespace)
+ trace("ok 3/4");
+
+ /* package method, with full path */
+ var t = flash.utils.getTimer();
+ if(t is int)
+ trace("ok 4/4");
+
+ trace("[exit]");
+ }
+ function test2() {
+ /* this test breaks in Flex */
+ var flash:Object = new Object();
+ flash["events"] = new Object();
+ trace(flash.events); //should work- no active import
+ }
+ }
+}
diff -Nru swftools-0.9.2+ds1/lib/as3/ok/precedence.as swftools-0.9.1/lib/as3/ok/precedence.as
--- swftools-0.9.2+ds1/lib/as3/ok/precedence.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/ok/precedence.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,151 @@
+package {
+
+ import flash.display.MovieClip
+
+ class C {
+ function f() {return new Array(1,2,3);}
+ }
+ public class Main extends flash.display.MovieClip {
+ var count:int = 1;
+ var num:int = 53;
+ function assert(b) {
+ if(b) {
+ trace("ok "+count+"/"+num);
+ } else {
+ trace("error "+count+"/"+num);
+ }
+ count = count + 1
+ }
+ function compare(x,y) {
+ assert(x==y);
+ }
+
+ var a:Array = new Array(1,2,3);
+ var b:int=10;
+ function f() {return a;}
+ function g() {return b;}
+ var i=0;
+
+ function Main() {
+
+ // test that ., [], (), @, ::, .. {x:y}, new all have the same precedence
+ // TODO: @, ::, ..
+
+ compare(this.f()[2] , (((this).f)())[2])
+ //compare(new C.f()[1],2); //breaks
+ compare(new C().f()[1],2);
+
+ // test that ., [], () have higher precedence than ++, --, -, ~, !, delete, typeof
+ // TODO: @, delete, typeof
+ var i:int=5,j:int;
+ this.i=0;
+ this.i++;compare(this.i,1);compare(i,5);
+ ++(this.a)[2]; compare(this.a[2],4);
+ delete this.f()[0];compare(String(this.a[0]), "undefined");
+
+ // test that ++ has higher precedence than unary -,~,!
+ compare(-i++,-5);
+ compare(!i++,false);
+ compare(~i++,~7);
+
+ // test that * / % have the same precedence
+ compare(3*10/15%4, 2)
+
+ // test that ++,--,~ have higher precedence than * / %
+ i = 0;j = 1;compare(++i*j++, 1)
+ i = 0;j = 1;compare(++i/j++, 1)
+ i = 2;j = 2;compare(++i%j++, 1)
+ compare( (~1*2) & 1, 0);
+
+ // test that +,- have lower precedence than * / %
+ compare(1+1*2, 3)
+ compare(5-4/2, 3)
+ compare(3-4%2, 3)
+ compare(2+1%2, 3)
+
+ // test that +, - have higher precedence than >>,<<,>>>
+ compare(4>>1+1, 1)
+ compare(4>>1-1, 4)
+ compare(4>>>1+1, 1)
+ compare(4>>>1-1, 4)
+ compare(1<<1+1, 4)
+ compare(4<<1-1, 4)
+
+ // test that >>,<< have higher precedence than <,>,<=,>=,==
+ compare(3 < 1<<2, true)
+ compare(4 <= 1<<2, true)
+ compare(2 > 8>>3, true)
+ compare(1 >= 8>>3, true)
+ compare(1 == 1<<0, true)
+ compare(1 == 1>>0, true)
+
+ // test that <,>,<=,>= have higher precedence than as, in
+ compare(1<2 as Boolean, true)
+ //compare(1<2 in [true,true,true], true)
+
+ // test that as,in have higher precedence than ==,!=
+ compare(1==1 as Boolean, false);
+ compare(1!=1 as Boolean, true);
+ compare(false == true is Boolean, false);
+ compare(true != true is Boolean, false);
+
+ // test that >,<,>=,<= have higher precedence than ==, !=, ===, !==
+ compare(true == 3<4, true)
+ compare(true != 3>4, true)
+ compare(true === 3<=4, true)
+ compare(true !== 3>=4, true)
+
+ // test that ==,!= have higher precedence than &
+ compare(3&4==4, 1)
+ compare(3&0!=4, 1)
+
+ // test that & has higher precedence than ^
+ compare(1^1&4, 1)
+
+ // test that ^ has higher precedence than |
+ compare(5|4^4, 5)
+
+ // test that | has higher precedence than &&
+ compare(false && 0|5, false)
+
+ // test that && has higher precedence than ||
+ compare(false && true || true, true)
+
+ // test that || has higher precedence than ?:
+ compare(true || false?11:0, 11)
+
+ // test that ?: and = have same precedence
+ var y = 0;
+ var x = false ? y=3 : y=4;
+ compare(y,4)
+ false ? y=3 : y=5;
+ compare(y,5)
+
+ // test that = is right-associative
+ x = y = 3;
+ compare(x,3)
+ compare(y,3)
+
+ // test that = has higher precedence than +=,-=,*=,/=,%=
+ x=4;y=10;
+ x += y = 4;
+ compare(x,8);
+
+ // test that +=,-=,*=,/=,%=,>>=,<<=,>>>= all have the same associativity
+ // TODO: %=,/=,-=,>>=,<<=,>>>=
+ x=2;y=3;
+ x *= y += 4;
+ assert(x==14 && y==7);
+
+ // test that , has lower precedence than +=
+ x=0;
+ var v=0;
+ v += 3,4;
+ compare(v,3)
+
+ trace("[exit]");
+ }
+
+ }
+}
+
diff -Nru swftools-0.9.2+ds1/lib/as3/ok/protected.as swftools-0.9.1/lib/as3/ok/protected.as
--- swftools-0.9.2+ds1/lib/as3/ok/protected.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/ok/protected.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,31 @@
+package {
+
+ public class A
+ {
+ protected var xx:Array = [];
+
+ public function A()
+ {
+ trace("ok");
+ }
+ }
+
+ public class B extends A
+ {
+ public function B()
+ {
+ super();
+ }
+ }
+
+ import flash.display.MovieClip
+ public class Main extends flash.display.MovieClip
+ {
+ public function Main()
+ {
+ var b:B = new B();
+ trace("[exit]");
+ }
+ }
+
+}
diff -Nru swftools-0.9.2+ds1/lib/as3/ok/prototype.as swftools-0.9.1/lib/as3/ok/prototype.as
--- swftools-0.9.2+ds1/lib/as3/ok/prototype.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/ok/prototype.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,23 @@
+package {
+ import flash.display.MovieClip;
+
+ public class Main extends flash.display.MovieClip {
+ function Main() {
+ function MySuper() {
+ this.ok3="ok 3/3";
+ }
+ function MyClass(ok1,ok2) {
+ this.ok1 = ok1;
+ this.ok2 = ok2;
+ };
+ MyClass.prototype = new MySuper;
+
+ var m = new MyClass("ok 1/3", "ok 2/3");
+ trace(m.ok1);
+ trace(m.ok2);
+ trace(m.ok3);
+
+ trace("[exit]");
+ }
+ }
+}
diff -Nru swftools-0.9.2+ds1/lib/as3/ok/reassign.as swftools-0.9.1/lib/as3/ok/reassign.as
--- swftools-0.9.2+ds1/lib/as3/ok/reassign.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/ok/reassign.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,22 @@
+package {
+ import flash.display.MovieClip
+
+ public class Main extends flash.display.MovieClip {
+
+ function Main() {
+
+ var a = [0,1];
+ var i = 0;
+
+ a[int(i++)] += 1;
+
+ if(a[0]==1) trace("ok 1/2");
+ else trace("error");
+ if(a[1]==1) trace("ok 2/2");
+ else trace("error");
+
+ trace("[exit]");
+ }
+ }
+}
+
diff -Nru swftools-0.9.2+ds1/lib/as3/ok/reconcile.as swftools-0.9.1/lib/as3/ok/reconcile.as
--- swftools-0.9.2+ds1/lib/as3/ok/reconcile.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/ok/reconcile.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,218 @@
+package {
+ import flash.display.MovieClip;
+ import flash.utils.ByteArray;
+
+ public class Main extends flash.display.MovieClip {
+
+ public function test0() {
+ // simple sanity test
+ while(false) {
+ var x1:String;
+ }
+ trace("ok 1/10");
+ }
+
+ // test whether local variables with default value "null"
+ // will be coerced to their object
+ public function test1() {
+ var dataBuffer:Array;
+ while(true) {
+ dataBuffer = new Array();
+ if(dataBuffer)
+ break;
+ }
+ trace("ok 2/10");
+ }
+
+ public function test2() {
+ var output:String = "";
+ while(output.length<1) {
+ output += "abc".charAt(0);
+ }
+ trace("ok 3/10");
+ }
+
+ public function test3() {
+ var k:uint;
+
+ while(true) {
+ for (var k:uint = 0; k < 4; k++) {
+ }
+ break;
+ }
+ trace("ok 4/10");
+ }
+
+ public var b:Boolean = false;
+
+ public function test4() {
+ var x:int;
+ var y:uint;
+ if(b) {
+ x = x+y;
+ y = y+x;
+ }
+ trace("ok 5/10");
+ }
+ public function test5() {
+ var x:int;
+ var y:uint;
+ var z:int;
+ if(b) {
+ x = x*y;
+ z = x*z;
+ }
+ trace("ok 6/10");
+ }
+ public function test6() {
+ var i:int = b?3.0:3;
+ var j:uint = b?3:"abc";
+ trace("ok 7/10");
+ }
+ public function test7() {
+ var j:Number = 0;
+ if(b) {
+ j += 8;
+ }
+ trace("ok 8/10");
+ }
+ public function s():String {
+ return "x";
+ }
+ public function test8() {
+ var x:String = "abcd";
+
+ var i:String = "test";
+ // test return types of system libraries
+ if(!b) {
+ i = x.charAt(0);
+ }
+ var a = "test";
+ // test return types of system libraries
+ if(!b) {
+ a = x.charAt(0);
+ }
+
+ // ...and local functions
+ if(!b) {
+ i = s();
+ }
+ trace("ok 9/10");
+ }
+
+ public function test_add() {
+ var i:int = 3;
+ var s:String = "4";
+ var any1 = "any1";
+ var any2 = "any2";
+ var xml:XML =
+ var xmllist:XMLList = XMLList()
+ var d1:Date = new Date();
+ var d2:Date = new Date();
+ var array1:Array = [1];
+ var array2:Array = [1,2];
+
+ /* int+String */
+ var z1a:Object;
+ var z1b:String;
+ if(b) {
+ z1a = i+s;
+ z1b = i+s;
+ }
+
+ /* String+int */
+ var z2a:Object;
+ var z2b:String;
+ if(b) {
+ z2a = s+i;
+ z2b = s+i;
+ }
+
+ /* any+any */
+ var z3a:*;
+ var z3b:Object;
+ if(b) {
+ z3a = any1+any2;
+ z3b = any1+any2;
+ }
+
+ /* any+String */
+ var z4a:Object;
+ var z4b:*;
+ if(b) {
+ z4a = any1+s;
+ z4b = any1+s;
+ }
+
+ /* xml+xmllist */
+ var z5a:Object;
+ var z5b:XMLList;
+ if(b) {
+ z5a = xml+xmllist;
+ z5b = xml+xmllist;
+ }
+
+ /* xmllist+xml */
+ var z6:Object;
+ if(b) {
+ z6 = xmllist+xml;
+ }
+
+ /* xml+any */
+ var z7a:*;
+ var z7b:XMLList;
+ if(b) {
+ z7a = xml+any1;
+ z7b = xml+any1;
+ }
+
+ /* date+date */
+ var z8a:Object;
+ var z8b:String;
+ if(b) {
+ z8a = d1+d2;
+ z8b = d1+d2;
+ }
+
+ /* date+any */
+ var z9a:Object;
+ var z9b:String;
+ if(b) {
+ z9a = d1+any1;
+ z9b = d1+any1;
+ }
+
+ /* any+date */
+ var z10a:Object;
+ var z10b:*;
+ if(b) {
+ z10a = any1+d1;
+ z10b = any1+d1;
+ }
+
+ /* array+array */
+ var z11a:Object;
+ var z11b:Array;
+ if(b) {
+ z11a = array1+array2;
+ z11b = array1+array2;
+ }
+ trace("ok 10/10");
+ }
+
+ public function Main() {
+ test0();
+ test1();
+ test2();
+ test3();
+ test4();
+ test5();
+ test6();
+ test7();
+ test8();
+ test_add();
+
+ trace("[exit]");
+ }
+ }
+}
diff -Nru swftools-0.9.2+ds1/lib/as3/ok/recursion.as swftools-0.9.1/lib/as3/ok/recursion.as
--- swftools-0.9.2+ds1/lib/as3/ok/recursion.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/ok/recursion.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,20 @@
+
+package {
+ import flash.display.MovieClip
+ import flash.geom.Point
+
+ public class Main extends flash.display.MovieClip {
+
+ function write(nr) {
+ trace("ok "+nr+"/3");
+ if(nr<3)
+ write(nr+1);
+ }
+
+ public function Main() {
+ write(1);
+
+ trace("[exit]");
+ }
+ }
+}
diff -Nru swftools-0.9.2+ds1/lib/as3/ok/regexp.as swftools-0.9.1/lib/as3/ok/regexp.as
--- swftools-0.9.2+ds1/lib/as3/ok/regexp.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/ok/regexp.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,35 @@
+
+package {
+ import flash.display.MovieClip
+
+ public class Main extends flash.display.MovieClip {
+ public function Main() {
+ /* test matching */
+ var r:RegExp = /ok \d\/\d/;
+ trace("ok 1/7".match(r));
+
+ /* test searching */
+ var s:String = "error OK 9/7 ok 2/7"
+ trace(s.substring(s.search(r)));
+
+ /* test /.../i syntax */
+ var r2:RegExp = /ok \d\/\d/i;
+ var s2:String = "error OK 3/7"
+ var s3:String = "error ok 3/7"
+ trace(s3.substring(s2.search(r2)));
+
+ /* test \n,\r,\t */
+ if(" .\n\r\t".search(/[\n][\r][\t]/) == 2) trace("ok 4/7");
+
+ /* test * at end of regexp */
+ if(" xxx ".search(/xx*/) == 2) trace("ok 5/7");
+
+ /* test quotes */
+ if(" \" ".search(/"/) == 1) trace("ok 6/7");
+ if(' \' '.search(/'/) == 1) trace("ok 7/7");
+
+ trace("[exit]");
+ }
+ }
+}
+
diff -Nru swftools-0.9.2+ds1/lib/as3/ok/resolve.as swftools-0.9.1/lib/as3/ok/resolve.as
--- swftools-0.9.2+ds1/lib/as3/ok/resolve.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/ok/resolve.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,30 @@
+package {
+
+ import flash.display.MovieClip
+
+ public class B extends C {
+ static var x:String = "error";
+
+ function f() {
+ /* the compiler should prefer the superclass x
+ over the static x */
+ return x;
+ }
+ }
+
+ public class C extends D {
+ }
+
+ public class D {
+ var x:String = "ok";
+ }
+
+
+ public class Main extends flash.display.MovieClip {
+ function Main() {
+ trace((new B()).f());
+ trace("[exit]");
+ }
+ }
+
+}
diff -Nru swftools-0.9.2+ds1/lib/as3/ok/return.as swftools-0.9.1/lib/as3/ok/return.as
--- swftools-0.9.2+ds1/lib/as3/ok/return.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/ok/return.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,24 @@
+package {
+
+ public class Test {
+ function Test() {
+ }
+ function getok1() {
+ return "ok 1/2";
+ }
+ function getok2():String {
+ return "ok 2/2";
+ }
+ };
+
+ import flash.display.MovieClip
+ public class Main extends flash.display.MovieClip {
+ function Main() {
+ trace((new Test).getok1());
+ var t = new Test;
+ trace(t.getok2());
+
+ trace("[exit]");
+ }
+ }
+}
diff -Nru swftools-0.9.2+ds1/lib/as3/ok/scope.as swftools-0.9.1/lib/as3/ok/scope.as
--- swftools-0.9.2+ds1/lib/as3/ok/scope.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/ok/scope.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,40 @@
+package some.multilevel.package {
+ public class ClassInMultiLevelPackage {
+ }
+}
+package some.other.multilevel.package {
+ import some.multilevel.package.*
+ public class ClassInOtherMultiLevelPackage extends ClassInMultiLevelPackage {
+ }
+}
+
+package I {
+ public interface I1 {
+ }
+ public interface I2 {
+ }
+ public interface I3 {
+ }
+}
+package A {
+
+ class A1 {
+ }
+ class A2 extends A1{
+ }
+ public class A3 extends A2 {
+ }
+
+}
+package B {
+ class B1 extends A.A3 implements I.I1,I.I2,I.I3{
+ }
+}
+package C {
+ public class Main extends flash.display.MovieClip {
+ function Main() {
+ trace("ok");
+ trace("[exit]");
+ }
+ }
+}
diff -Nru swftools-0.9.2+ds1/lib/as3/ok/slots.as swftools-0.9.1/lib/as3/ok/slots.as
--- swftools-0.9.2+ds1/lib/as3/ok/slots.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/ok/slots.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,23 @@
+package {
+ import flash.display.MovieClip;
+ public class Main extends flash.display.MovieClip {
+ var s1 = "ok 4/7";
+ function ok1() {trace("ok 1/7");}
+ var s2 = "ok 5/7";
+ function ok2() {trace("ok 2/7");}
+ const s3 = "ok 6/7"
+ function ok3() {trace("ok 3/7");}
+ var s4 = "ok 7/7";
+
+ function Main() {
+ ok1();
+ ok2();
+ ok3();
+ trace(this.s1);
+ trace(this.s2);
+ trace(this.s3);
+ trace(this.s4);
+ trace("[exit]");
+ }
+ }
+}
diff -Nru swftools-0.9.2+ds1/lib/as3/ok/static.as swftools-0.9.1/lib/as3/ok/static.as
--- swftools-0.9.2+ds1/lib/as3/ok/static.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/ok/static.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,50 @@
+package {
+ import flash.display.MovieClip;
+ import flash.events.*
+
+ public class Main extends flash.display.MovieClip {
+ static var ok1 = "ok 1/12";
+ static var ok2:String = "ok 2/12";
+
+ static function ok5() {
+ trace("ok 5/12");
+ }
+
+ static var ok3:String = "ok 6/12";
+ static var ok4:String = "ok 7/12";
+ static function f(s) {
+ trace(s);
+ trace(ok4);
+ }
+ static var ok8:String = "ok 8/12";
+
+ static var _ok9:String = "ok 9/12";
+ var ok9 = Main._ok9;
+
+ static var ok11:String = "ok 11/12";
+ var ok11:int = 12;
+
+ function Main() {
+ trace(ok1);
+ trace(ok2);
+ ok1 = "ok 3/12";
+ ok2 = "ok 4/12";
+ trace(ok1);
+ trace(ok2);
+ ok5();
+ f(ok3);
+ trace(Main.ok8);
+ trace(this.ok9);
+
+ XML.prettyPrinting = true;
+
+ if(TextEvent.TEXT_INPUT == "textInput")
+ trace("ok 10/12");
+
+ trace(Main.ok11);
+ trace("ok "+ok11+"/12");
+
+ trace("[exit]");
+ }
+ }
+}
diff -Nru swftools-0.9.2+ds1/lib/as3/ok/staticinit.as swftools-0.9.1/lib/as3/ok/staticinit.as
--- swftools-0.9.2+ds1/lib/as3/ok/staticinit.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/ok/staticinit.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,38 @@
+package {
+ import flash.display.MovieClip
+
+ public class A {
+ if(B == null)
+ trace("error");
+ B.b();
+ static function a() {trace("ok 5/5")}
+ }
+ public class B {
+ static function b() {trace("ok 4/5")}
+ }
+ public class C {
+ if(A == null || B == null)
+ trace("error");
+ A.a();
+ }
+
+ public class Main extends flash.display.MovieClip {
+ public static const types:Array = ["error", "ok 1/5", "error"];
+
+ public static var fptr:Function = Main.f;
+
+ public var c1="ok 3/5";
+ public var c2=c1;
+
+ public static function f() {
+ trace(types[1]);
+ trace("ok 2/5");
+ }
+
+ function Main() {
+ fptr();
+ trace(c2);
+ trace("[exit]");
+ }
+ }
+}
diff -Nru swftools-0.9.2+ds1/lib/as3/ok/staticself.as swftools-0.9.1/lib/as3/ok/staticself.as
--- swftools-0.9.2+ds1/lib/as3/ok/staticself.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/ok/staticself.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,17 @@
+package
+{
+ public class T
+ {
+ }
+ public class Main
+ {
+ public static const t = new T();
+ public static const BASE = new Main();
+
+ function Main()
+ {
+ trace("ok");
+ trace("[exit]");
+ }
+ }
+}
diff -Nru swftools-0.9.2+ds1/lib/as3/ok/strings2.as swftools-0.9.1/lib/as3/ok/strings2.as
--- swftools-0.9.2+ds1/lib/as3/ok/strings2.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/ok/strings2.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,30 @@
+
+package {
+ import flash.display.MovieClip
+ public class Main extends flash.display.MovieClip {
+
+ function Main() {
+ var ok1 = "ok \
+1/5";
+ var ok2 = "ok \x32/\x35";
+ var ok3 = "ok \u0033/\u0035";
+ trace(ok1);
+ trace(ok2);
+ trace(ok3);
+ var x = "\uFFED\uFFEE"
+ if(x.charAt(1) == "\uFFEE") {
+ trace("ok 4/5");
+ }
+
+ var y = "\n\r\t\\\7";
+ if(y.charAt(0) == "\n" &&
+ y.charAt(1) == "\r" &&
+ y.charAt(2) == "\t" &&
+ y.charAt(3) == "\\" &&
+ y.charAt(4) == "\7")
+ trace("ok 5/5")
+ trace("[exit]");
+ }
+ }
+}
+
diff -Nru swftools-0.9.2+ds1/lib/as3/ok/strings.as swftools-0.9.1/lib/as3/ok/strings.as
--- swftools-0.9.2+ds1/lib/as3/ok/strings.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/ok/strings.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,42 @@
+package {
+ import flash.display.MovieClip
+ public class Main extends flash.display.MovieClip {
+
+ function get mystring(s="s\0s\xff") {
+ return s;
+ }
+
+ function Main() {
+ var email = "test@test.de";
+ if(email.length == 12) trace("ok 1/7");
+ if(email.charAt(4)!='@') trace("error");
+
+ var x;
+ var y:Boolean=false;
+ for(x=0;x};
+
+ This XML doesn't do anything!
+
+ ;
+ /Neither does this regexp!/
+ ;
+
+ var y = 3;
+ test
+
+ assert(true);
+
+ var f2 = function(s:String) {assert(true);}
+ var f3 = function(s:String) {assert(true);}
+
+ f2();
+
+ //f3();
+
+ /* ----- xml objects ----- */
+
+ var x1:XML =
+ Branch 1
+ Branch 2
+
+
+ assert(typeof(x1)=="xml");
+
+ /* ------ access --------- */
+
+ assert(x1. * == x1.children())
+ assert((x1.*)[0].text() == "Branch 1")
+ assert(x1.branch[0] == x1.child("branch")[0])
+ assert((x1.*.@bname)[0] == "t1");
+
+ assert(x1.@name.parent() == x1);
+ assert(x1.@["name"].parent() == x1);
+ var s1=
+ assert(s1.@* == s1.attributes())
+
+ /* ------ comments ------- */
+
+ var x3 = Test;
+ assert(x3.toString() == "Test")
+
+ /* ------ descendants ---- */
+
+ var x4 =
+
+ v1
+ e1
+
+
+ e2
+ v2
+
+
+ assert(x4..l3[0] == x4.l2.l3)
+
+ var s:String="";
+ for each(var c:XML in x4..l3) {
+ s += c.toString();
+ }
+ assert(s=="v1v2");
+
+ s="";
+ for each(var e:XML in x1..@bname) {
+ s += e.toString();
+ }
+ assert(s=="t1t2");
+
+ s="";
+ for each(var e in x1..@*) {
+ s += e.toString();
+ }
+ assert(s=="testt1t2");
+
+ /* ----- filtering ----- */
+
+ var x5:XML =
+ John Doe
+ Ellen Doe
+ John Smith
+ Jane Smith
+
+
+ var l:XMLList = x5.*;
+ var l2:XMLList = l.(@gender=="m");
+ assert(l2.length()==2 && l2[0].text()=="John Doe" && l2[1].text()=="John Smith");
+ l2 = x5.*.(@gender=="f").(hasOwnProperty("@id") && @id>2)
+ assert(l2.text() =="Jane Smith");
+
+ /* ----- replacement ----- */
+
+ var x10:XML =
+ var x11:XML =
+
+ assert(x10 != x11);
+ x11.b.d = ;
+ assert(x10 != x11);
+ x11.b.@a = "x";
+ assert(x10 == x11);
+ x11.b.@["a"] = "y";
+ assert(x10 != x11);
+ x11.b.@["a"] = "x";
+ assert(x10 == x11);
+
+ var x12:XML = ;
+ x12.a += ;
+
+ assert(x12 == );
+
+ x12.* = ;
+ assert(x12 == );
+ x12.* = ;
+
+ /* ----- deletion ----- */
+
+ delete x12.a
+ assert(x12 == );
+ delete x12.*
+ assert(x12 == );
+ delete x10.b.c
+ delete x10.b.@a
+ assert(x10 == );
+ delete x11.b.c
+ delete x11.b.@*
+ assert(x10 == x11);
+
+ /* ----- special characters ----- */
+
+ trace("[special characters]");
+
+ var x20 = >& ;
+ assert(x20.toString() == ">&");
+ var x21 = ;
+ assert(x21.@a == "\"<>");
+ var x22 = ;
+
+ /* ----- substitution ----- */
+
+ trace("[substitution]");
+ x1.@t = "x";
+ var x2:XML = <{"tree"} {"na"+"me"}="test" {"t=\"x\""}>
+ <{{three: "branch"}["three"]} bname={"t1"}>{"Branch" + " " + 1}{"branch"}>
+ Branch 2
+
+ assert(x1 == x2);
+
+ trace("[exit]");
+ }
+ }
+}
diff -Nru swftools-0.9.2+ds1/lib/as3/ok/xml_ns.as swftools-0.9.1/lib/as3/ok/xml_ns.as
--- swftools-0.9.2+ds1/lib/as3/ok/xml_ns.as 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/ok/xml_ns.as 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,48 @@
+package {
+ import flash.display.MovieClip
+ public class Main extends flash.display.MovieClip {
+ var count:int = 1;
+ var num:int = 9;
+ function assert(b:Boolean) {
+ if(b) {
+ trace("ok "+count+"/"+num);
+ } else {
+ trace("error "+count+"/"+num);
+ }
+ count = count + 1
+ }
+ function Main() {
+ var x:XML =
+
+ P1
+ P2
+ P3
+
+
+ var top:Namespace = x.namespace();
+ var ns1:Namespace = x.namespace("test1");
+ var ns2:Namespace = x.namespace("test2");
+ var ns3:Namespace = x.namespace("test3");
+ assert(ns1 == new Namespace("http://www.quiss.org/test1/"));
+ assert(ns2 == new Namespace("http://www.quiss.org/test2/"));
+ assert(x.ns1::test == "P1");
+ assert(x.ns2::test == "P2");
+
+ assert(x.ns1::* == "P1")
+
+ default xml namespace = ns2;
+ assert(x.test == "P2")
+
+ assert(x.*::* == (x.ns1::*+x.ns2::*+x.ns3::*))
+ //attribute with a namespace:
+ assert(x..@*::* == "b");
+
+ x.ns2::test = x.ns3::test;
+ assert(x..@a.toString() == "bb");
+
+ trace("[exit]");
+ }
+ }
+}
diff -Nru swftools-0.9.2+ds1/lib/as3/optimizations.txt swftools-0.9.1/lib/as3/optimizations.txt
--- swftools-0.9.2+ds1/lib/as3/optimizations.txt 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/optimizations.txt 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,20 @@
+* "push;pop" can be removed (if there's no jumppoint)
+* "push;coerce;pop" can be removed (if there's no jumppoint)
+* "getlocal_i;pop" can be removed
+* "goto next;next:" can be removed (if there's no jumppoint)
+* "setlocal_i;getlocal_i" can be changed to "dup;setlocal_i"
+* for a variable without any getlocal_i, all dup;setlocal_i can be removed
+* getlocal can be changed to getlocal_i for i<4, same for setlocal
+* greater followed by iftrue can be reduced to ifgt
+* equals followed by iffalse can be reduced to ifne (etc.)
+* callproperty;(coerce);pop can changed to callpropvoid
+* label can be removed
+* "getlocal_i;setlocal_i" can be removed
+* "dup;xxx;pop" can be reduced to xxx (xxx=setlocal_i, setglobalslot, pushscope)
+* "getlocal_i;increment;setlocal_i" can be replaced by inclocal_i
+* [iffalse xx;jump yy;xx: -> iftrue yy]
+* a jump to a jump can be redirected
+* sort variable indices by usage
+* coerce*;returnvalue can be reduced to returnvalue
+* a kill before a return can be eliminated
+* setlocal_i;getlocal_j;getlocal_i can be changed to dup;setlocal_i;getlocal_j,swap (makes it possible to remove i if not otherwise used)
diff -Nru swftools-0.9.2+ds1/lib/as3/parser.y swftools-0.9.1/lib/as3/parser.y
--- swftools-0.9.2+ds1/lib/as3/parser.y 1970-01-01 00:00:00.000000000 +0000
+++ swftools-0.9.1/lib/as3/parser.y 2012-06-20 15:37:18.000000000 +0000
@@ -0,0 +1,2254 @@
+/* parser.y
+
+ Routines for compiling Flash2 AVM2 ABC Actionscript
+
+ Extension module for the rfxswf library.
+ Part of the swftools package.
+
+ Copyright (c) 2008 Matthias Kramm
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+%{
+#include
+#include
+#include
+#include "abc.h"
+#include "pool.h"
+#include "files.h"
+#include "common.h"
+#include "tokenizer.h"
+#include "registry.h"
+#include "code.h"
+#include "opcodes.h"
+#include "compiler.h"
+#include "expr.h"
+#include "initcode.h"
+#include "parser_help.h"
+
+extern int a3_lex();
+
+%}
+
+//%glr-parser
+//%expect-rr 1
+%error-verbose
+
+%union tokenunion {
+ enum yytokentype token;
+
+ classinfo_t*classinfo;
+ classinfo_list_t*classinfo_list;
+ slotinfo_t*slotinfo;
+ slotinfo_list_t*slotinfo_list;
+
+ int number_int;
+ unsigned int number_uint;
+ double number_float;
+ code_t*code;
+ typedcode_t value;
+ //typedcode_list_t*value_list;
+ codeandnumber_t value_list;
+ param_t* param;
+ params_t params;
+ string_t str;
+ char*id;
+ constant_t*constant;
+ for_start_t for_start;
+ abc_exception_t *exception;
+ regexp_t regexp;
+ modifiers_t flags;
+ namespace_decl_t* namespace_decl;
+ node_t*node;
+ struct {
+ abc_exception_list_t *l;
+ code_t*finally;
+ } catch_list;
+}
+
+
+%token T_IDENTIFIER
+%token T_STRING
+%token T_REGEXP
+%token T_EMPTY
+%token T_INT
+%token T_UINT
+%token T_FLOAT
+
+%token T_FOR "for"
+%token T_WHILE "while"
+%token T_DO "do"
+%token T_SWITCH "switch"
+
+%token KW_IMPLEMENTS "implements"
+%token KW_NAMESPACE "namespace"
+%token KW_PACKAGE "package"
+%token KW_PROTECTED "protected"
+%token KW_ARGUMENTS "arguments"
+%token KW_PUBLIC "public"
+%token KW_PRIVATE "private"
+%token KW_USE "use"
+%token KW_INTERNAL "internal"
+%token KW_NEW "new"
+%token KW_NATIVE "native"
+%token KW_FUNCTION "function"
+%token KW_FINALLY "finally"
+%token KW_UNDEFINED "undefined"
+%token KW_NAN "NaN"
+%token KW_CONTINUE "continue"
+%token KW_CLASS "class"
+%token KW_CONST "const"
+%token KW_CATCH "catch"
+%token KW_CASE "case"
+%token KW_SET "set"
+%token KW_VOID "void"
+%token KW_THROW "throw"
+%token KW_STATIC "static"
+%token KW_WITH "with"
+%token KW_INSTANCEOF "instanceof"
+%token KW_IMPORT "import"
+%token KW_RETURN "return"
+%token KW_TYPEOF "typeof"
+%token KW_INTERFACE "interface"
+%token KW_NULL "null"
+%token KW_VAR "var"
+%token KW_DYNAMIC "dynamic"
+%token KW_OVERRIDE "override"
+%token KW_FINAL "final"
+%token KW_EACH "each"
+%token KW_GET "get"
+%token KW_TRY "try"
+%token KW_SUPER "super"
+%token KW_EXTENDS "extends"
+%token KW_FALSE "false"
+%token KW_TRUE "true"
+%token KW_BOOLEAN "Boolean"
+%token KW_UINT "uint"
+%token KW_INT "int"
+%token KW_NUMBER "Number"
+%token KW_STRING "String"
+%token KW_DEFAULT "default"
+%token KW_DEFAULT_XML "default xml"
+%token KW_DELETE "delete"
+%token KW_IF "if"
+%token KW_ELSE "else"
+%token KW_BREAK "break"
+%token KW_IS "is"
+%token KW_IN "in"
+%token KW_AS "as"
+
+%token T_DICTSTART "{ (dictionary)"
+%token T_EQEQ "=="
+%token T_EQEQEQ "==="
+%token T_NE "!="
+%token T_NEE "!=="
+%token T_LE "<="
+%token T_GE ">="
+%token T_ORBY "|="
+%token T_DIVBY "/="
+%token T_MODBY "%="
+%token T_MULBY "*="
+%token T_ANDBY "&="
+%token T_PLUSBY "+="
+%token T_MINUSBY "-="
+%token T_XORBY "^="
+%token T_SHRBY ">>="
+%token T_SHLBY "<<="
+%token T_USHRBY ">>>="
+%token T_OROR "||"
+%token T_ANDAND "&&"
+%token T_COLONCOLON "::"
+%token T_MINUSMINUS "--"
+%token T_PLUSPLUS "++"
+%token T_DOTDOT ".."
+%token T_DOTDOTDOT "..."
+%token T_SHL "<<"
+%token T_USHR ">>>"
+%token T_SHR ">>"
+
+%type EMBED_START // CONDITIONAL_COMPILATION
+%type FOR_START
+%type X_IDENTIFIER PACKAGE FOR_IN_INIT MAYBE_IDENTIFIER ID_OR_NS SUBNODE
+%type NAMESPACE_ID
+%type VARCONST
+%type CODE
+%type CODEPIECE CODE_STATEMENT
+%type CODEBLOCK IF_CODEBLOCK MAYBECODE MAYBE_CASE_LIST CASE_LIST DEFAULT CASE SWITCH WITH
+%type PACKAGE_DECLARATION SLOT_DECLARATION SLOT_LIST ONE_SLOT
+%type FUNCTION_DECLARATION PACKAGE_INITCODE
+%type VARIABLE_DECLARATION ONE_VARIABLE VARIABLE_LIST THROW
+%type CATCH FINALLY
+%type CATCH_LIST CATCH_FINALLY_LIST
+%type CLASS_DECLARATION
+%type NAMESPACE_DECLARATION
+%type INTERFACE_DECLARATION
+%type VOIDEXPRESSION
+%type EXPRESSION NONCOMMAEXPRESSION
+%type MAYBEEXPRESSION
+%type DELETE
+%type E COMMA_EXPRESSION
+%type VAR_READ
+%type